diff --git a/.gitignore b/.gitignore index 79c70512..563e7a4e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ **/.lake # Rust -/target +**/target # Nix result* diff --git a/Benchmarks/CompileInit.lean b/Benchmarks/CompileInit.lean new file mode 100644 index 00000000..2a073666 --- /dev/null +++ b/Benchmarks/CompileInit.lean @@ -0,0 +1,3 @@ +import Init + +def main : IO Unit := pure () diff --git a/Cargo.lock b/Cargo.lock index 7de24578..e6e1f132 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,6 +46,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "aiur" +version = "0.1.0" +dependencies = [ + "indexmap", + "multi-stark", + "rayon", + "rustc-hash", + "tracing", + "tracing-texray", +] + [[package]] name = "allocator-api2" version = "0.2.21" @@ -61,6 +73,56 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.60.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.60.2", +] + [[package]] name = "anyhow" version = "1.0.102" @@ -163,6 +225,14 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" +[[package]] +name = "bignat" +version = "0.1.0" +source = "git+https://github.com/argumentcomputer/lean-ffi.git?rev=839b405de708b80504fda39abe1402114b4135a5#839b405de708b80504fda39abe1402114b4135a5" +dependencies = [ + "num-bigint", +] + [[package]] name = "bincode" version = "2.0.1" @@ -299,17 +369,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chacha20" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.0", - "rand_core 0.10.1", -] - [[package]] name = "chrono" version = "0.4.44" @@ -352,6 +411,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "const-oid" version = "0.10.2" @@ -794,7 +859,10 @@ version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a" dependencies = [ + "anstream", + "anstyle", "env_filter", + "jiff", "log", ] @@ -1694,6 +1762,12 @@ dependencies = [ "z32", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + [[package]] name = "itertools" version = "0.13.0" @@ -1719,10 +1793,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] -name = "ix_rs" +name = "ix-common" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "indexmap", + "quickcheck", + "quickcheck_macros", + "rustc-hash", +] + +[[package]] +name = "ix-compile" +version = "0.1.0" +dependencies = [ + "anyhow", + "bignat", + "blake3", + "dashmap", + "indexmap", + "itertools 0.14.0", + "ix-common", + "ix-kernel", + "ixon", + "num-bigint", + "rayon", + "rustc-hash", + "sha2 0.10.9", +] + +[[package]] +name = "ix-ffi" version = "0.1.0" dependencies = [ + "aiur", "anyhow", + "bignat", "bincode", "blake3", "bytes", @@ -1732,15 +1839,15 @@ dependencies = [ "iroh", "iroh-base", "itertools 0.14.0", + "ix-common", + "ix-compile", + "ix-kernel", + "ixon", "lean-ffi", - "memmap2", "mimalloc", "multi-stark", "n0-error", "num-bigint", - "quickcheck", - "quickcheck_macros", - "rand 0.10.1", "rayon", "rustc-hash", "serde", @@ -1752,6 +1859,69 @@ dependencies = [ "tracing-texray", ] +[[package]] +name = "ix-kernel" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "dashmap", + "env_logger", + "indexmap", + "itertools 0.14.0", + "ix-common", + "ixon", + "log", + "num-bigint", + "quickcheck", + "quickcheck_macros", + "rayon", + "rustc-hash", +] + +[[package]] +name = "ixon" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "dashmap", + "indexmap", + "ix-common", + "memmap2", + "num-bigint", + "quickcheck", + "quickcheck_macros", + "rayon", + "rustc-hash", + "sha2 0.10.9", + "tiny-keccak", +] + +[[package]] +name = "jiff" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-static" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "js-sys" version = "0.3.97" @@ -1773,8 +1943,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lean-ffi" version = "0.1.0" -source = "git+https://github.com/argumentcomputer/lean-ffi?rev=cc98ebf67bf453ac3827cb767f78b13ea674dd6a#cc98ebf67bf453ac3827cb767f78b13ea674dd6a" +source = "git+https://github.com/argumentcomputer/lean-ffi.git?rev=839b405de708b80504fda39abe1402114b4135a5#839b405de708b80504fda39abe1402114b4135a5" dependencies = [ + "bignat", "bindgen", "cc", "num-bigint", @@ -2356,6 +2527,12 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + [[package]] name = "opaque-debug" version = "0.3.1" @@ -2768,6 +2945,15 @@ dependencies = [ "serde", ] +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] + [[package]] name = "portmapper" version = "0.15.0" @@ -2998,7 +3184,6 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" dependencies = [ - "chacha20", "getrandom 0.4.2", "rand_core 0.10.1", ] @@ -3973,6 +4158,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "1.23.1" diff --git a/Cargo.toml b/Cargo.toml index 58b90be3..c0b0b64f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,57 +1,63 @@ -[package] -name = "ix_rs" +[workspace] +members = [ + "crates/aiur", + "crates/common", + "crates/compile", + "crates/ffi", + "crates/ixon", + "crates/kernel", +] +# `zisk/` and `sp1/` are their own Cargo workspaces (guest + host) built via +# the respective zkVM toolchains; excluded so host workspace ops don't pick +# them up. +exclude = ["zisk", "sp1"] +resolver = "2" + +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" + +[workspace.package] version = "0.1.0" edition = "2024" +license = "MIT OR Apache-2.0" + +[workspace.dependencies] +# Internal crates +aiur = { path = "crates/aiur" } +ix-common = { path = "crates/common" } +ix-compile = { path = "crates/compile" } +ixon = { path = "crates/ixon" } +ix-kernel = { path = "crates/kernel" } -[lib] -crate-type = ["staticlib"] +# lean-ffi tree (lean-ffi crate + factored-out bignat sub-crate) +bignat = { git = "https://github.com/argumentcomputer/lean-ffi.git", rev = "839b405de708b80504fda39abe1402114b4135a5" } +lean-ffi = { git = "https://github.com/argumentcomputer/lean-ffi.git", rev = "839b405de708b80504fda39abe1402114b4135a5" } -[dependencies] +# External shared deps anyhow = "1" blake3 = "1.8.4" +dashmap = "6.1.0" +indexmap = "2" itertools = "0.14.0" -indexmap = { version = "2", features = ["rayon"] } -lean-ffi = { git = "https://github.com/argumentcomputer/lean-ffi", rev = "cc98ebf67bf453ac3827cb767f78b13ea674dd6a" } +log = "0.4" +memmap2 = "0.9" mimalloc = { version = "0.1", default-features = false } multi-stark = { git = "https://github.com/argumentcomputer/multi-stark.git", rev = "9ecab51d553445c0cc7b571af00a76b8a83a6f8c" } num-bigint = "0.4.6" +quickcheck = "1.0.3" +quickcheck_macros = "1.0.0" rayon = "1" rustc-hash = "2" -tiny-keccak = { version = "2", features = ["keccak"] } -dashmap = { version = "6.1.0", features = ["rayon"] } -memmap2 = "0.9" sha2 = "0.10" -# Iroh dependencies -bytes = { version = "1.10.1", optional = true } -tokio = { version = "1.44.1", optional = true } -iroh = { version = "0.97", optional = true } -iroh-base = { version = "0.97", optional = true } -n0-error = { version = "0.1", optional = true } -getrandom = { version = "0.3", optional = true } +tiny-keccak = { version = "2", features = ["keccak"] } tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["env-filter"] } tracing-texray = { git = "https://github.com/argumentcomputer/tracing-texray", rev = "8ce04e3422cd48e68ef47fab95dba7d06b8c368c" } -bincode = { version = "2.0.1", optional = true } -serde = { version = "1.0.219", features = ["derive"], optional = true } - -[dev-dependencies] -quickcheck = "1.0.3" -rand = "0.10.1" -quickcheck_macros = "1.0.0" - -[features] -default = [] -parallel = ["multi-stark/parallel"] -test-ffi = [] -net = ["bytes", "tokio", "iroh", "iroh-base", "n0-error", "getrandom", "bincode", "serde" ] - -[profile.dev] -panic = "abort" - -[profile.release] -panic = "abort" -[lints.rust] +[workspace.lints.rust] invalid_reference_casting = "warn" nonstandard_style = "warn" rust_2018_idioms = { level = "warn", priority = -1 } @@ -60,7 +66,7 @@ unreachable_pub = "warn" unused_lifetimes = "warn" unused_qualifications = "warn" -[lints.clippy] +[workspace.lints.clippy] all = { level = "warn", priority = -1 } cast_lossless = "warn" cast_possible_truncation = "warn" diff --git a/Ix/Cli/CompileCmd.lean b/Ix/Cli/CompileCmd.lean index a00f95e5..0fcb5713 100644 --- a/Ix/Cli/CompileCmd.lean +++ b/Ix/Cli/CompileCmd.lean @@ -34,6 +34,8 @@ def runCompileCmd (p : Cli.Parsed) : IO UInt32 := do let pathStr := path.as! String let outPath : String := (p.flag? "out").map (·.as! String) |>.getD (defaultOutPathFor pathStr) + let rootName? : Option Lean.Name := + (p.flag? "root").map (·.as! String |>.toName) buildFile pathStr let leanEnv ← getFileEnv pathStr diff --git a/Ix/Meta.lean b/Ix/Meta.lean index 41cfa980..4430c52e 100644 --- a/Ix/Meta.lean +++ b/Ix/Meta.lean @@ -88,17 +88,41 @@ def fetchMathlibCache (cwd : Option FilePath) : IO Unit := do if exitCode != 0 then throw $ IO.userError "lake exe cache get failed" +/-- Walk up from `start` looking for `lake-manifest.json`. -/ +partial def findLakeRoot (start : FilePath) : IO (Option FilePath) := do + if ← (start / "lake-manifest.json").pathExists then + return some start + match start.parent with + | none => return none + | some p => if p == start then return none else findLakeRoot p + +/-- Walk up from `cur` collecting directory names until reaching `root`, +yielding the path components between them (in top-down order). -/ +partial def collectRelParts (root cur : FilePath) (acc : List String) : Option (List String) := + if cur == root then some acc + else match cur.fileName, cur.parent with + | some name, some par => + if par == cur then none else collectRelParts root par (name :: acc) + | _, _ => none + /-- Build the Lean module at the given file path using Lake. Also fetches Mathlib cache if the project depends on it. -/ def buildFile (path : FilePath) : IO Unit := do let path ← IO.FS.realPath path - let some moduleName := path.fileStem + let some stem := path.fileStem | throw $ IO.userError s!"cannot determine module name from {path}" - fetchMathlibCache path.parent + let some parent := path.parent + | throw $ IO.userError s!"cannot determine parent of {path}" + let some root ← findLakeRoot parent + | throw $ IO.userError s!"no lake-manifest.json found at or above {parent}" + let some relParts := collectRelParts root parent [] + | throw $ IO.userError s!"{path} is not under {root}" + let moduleName := ".".intercalate (relParts ++ [stem]) + fetchMathlibCache root let child ← IO.Process.spawn { cmd := "lake" args := #["build", moduleName] - cwd := path.parent + cwd := root stdout := .inherit stderr := .inherit } diff --git a/README.md b/README.md index 0f7af7e6..23224f1c 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,204 @@ Compiler performance benchmarks are tracked at https://bencher.dev/console/proje **Rust tests:** `cargo test` or `cargo nextest run` +### Proving under SP1 + +The Ix kernel typechecker has an SP1 guest at `sp1/guest/` driven by a host at +`sp1/host/`. The workflow is two steps: first compile a Lean program to a `.ixe` +serialized `Ixon.Env`, then feed that file to the SP1 host to either execute or +prove the typecheck. + +**Nix users only:** enter the SP1 dev shell first to pick up `cargo-prove` and +the succinct Rust toolchain: + +``` +nix develop .#sp1 +``` + +Non-Nix users: install the SP1 toolchain manually per the +[SP1 docs](https://docs.succinct.xyz/docs/sp1/getting-started/install). + +1. **Compile a `.ixe` from a Lean file.** Pass `--path` to the Lean source, + `--root` to slice the environment to the transitive closure of one constant, + and `--out` for the output path. For example, to compile + `Nat.add_comm` from the benchmark file: + + ``` + lake exe ix compile --path Benchmarks/CheckNatAddComm.lean \ + --root Nat.add_comm \ + --out nataddcomm.ixe + ``` + + Omitting `--root` emits the entire environment; omitting `--out` defaults to + the lowercased input stem plus `.ixe` (e.g. `checknataddcomm.ixe`). + +2. **Execute or prove under SP1.** From `sp1/host/`, run the host with `--ixe` + pointing at the file produced above: + + ``` + cd sp1/host + # Execute the kernel typecheck in the SP1 VM (no proof), prints failures + cycles + RUST_LOG=info cargo run --release -- --execute --ixe ../../nataddcomm.ixe + # Generate and verify a compressed SP1 proof of the same typecheck (CPU) + RUST_LOG=info cargo run --release -- --ixe ../../nataddcomm.ixe + ``` + + With no `--ixe`, the host runs against an empty `Ixon.Env`. + + **Kernel modes.** The default is Anon mode (metadata-erased kernel with + lazy on-demand ingress — matches Aiur's `kernel_check_test` semantics). + Pass `--meta` to run Meta mode (preserves names + dup-level-param check; + eager full-env ingress). Both prove the same structural typecheck; Meta + is strictly more constrained but slightly more expensive in cycles. + + **GPU proving.** Build with the `cuda` feature and set `SP1_PROVER=cuda` + at runtime: + + ``` + SP1_PROVER=cuda RUST_LOG=info cargo run --release --features cuda -- \ + --ixe ../../nataddcomm.ixe + ``` + + See the [SP1 CUDA docs](https://docs.succinct.xyz/docs/sp1/generating-proofs/hardware-acceleration/cuda) + for prerequisites (Docker + an NVIDIA GPU with CUDA 12+). + +### Proving under Zisk + +The Ix kernel typechecker also has a Zisk guest at `zisk/guest/` driven by a +host at `zisk/host/`. The workflow mirrors the SP1 one — first compile a Lean +program to a `.ixe`, then feed it to the Zisk host to either execute or prove +the typecheck. + +**Nix users only:** enter the Zisk dev shell first to pick up `cargo-zisk`, +`ziskemu`, and the RISC-V toolchain needed to build the guest: + +``` +nix develop .#zisk +``` + +Non-Nix users: install Zisk manually per the +[Zisk install docs](https://0xpolygonhermez.github.io/zisk/getting_started/installation.html). + +1. **Compile a `.ixe` from a Lean file.** Same as for SP1: + + ``` + lake exe ix compile --path Benchmarks/CheckNatAddComm.lean \ + --root Nat.add_comm \ + --out nataddcomm.ixe + ``` + +2. **Execute or prove under Zisk.** From `zisk/`, run the host with `--ixe`: + + ``` + cd zisk + # Execute the kernel typecheck in the Zisk VM (no proof), prints cycles + RUST_LOG=info cargo run --release -- --execute --ixe ../nataddcomm.ixe + # Run the constraint checker without generating a proof + RUST_LOG=info cargo run --release -- --verify-constraints --ixe ../nataddcomm.ixe + # Generate and verify a VadcopFinal proof of the same typecheck (CPU) + RUST_LOG=info cargo run --release -- --ixe ../nataddcomm.ixe + ``` + + With no `--ixe`, the host runs against an empty `Ixon.Env`. The host's + `build.rs` invokes `zisk_sdk::build_program("../guest")`, so `cargo run` + transparently rebuilds the guest ELF whenever its sources change. + + **Kernel modes.** Same `--meta` flag as the SP1 host (default is Anon + with lazy on-demand ingress; `--meta` switches to Meta with eager + full-env ingress). + + **GPU proving.** Pass `--gpu` at runtime — Zisk's prover backend ships + with CUDA support by default (the `cpu-only` Cargo feature is opt-out + and is not set here): + + ``` + RUST_LOG=info cargo run --release -- --gpu --ixe ../nataddcomm.ixe + ``` + + Requires a CUDA-capable GPU and the matching CUDA runtime libraries + visible to the linker (`LD_LIBRARY_PATH`). The Nix `.#zisk` shell wires + these up automatically; for non-Nix setups follow the + [Zisk install docs](https://0xpolygonhermez.github.io/zisk/getting_started/installation.html). + + **Memlock limit (Linux).** Zisk's assembly emulator `mmap`s ROM and + trace buffers with `MAP_LOCKED`, so the per-process locked-memory + rlimit (`ulimit -l`) must be high enough to back the trace. Many + Linux distros default to a low memlock limit; the Linux kernel + itself sets non-privileged processes to `RAM / 8`, which is still + too small for larger envs. Symptom: `mmap(rom) errno=11=Resource + temporarily unavailable` followed by `Shmem creation … failed with + exit status: 255` during `STARTING_ASM_MICROSERVICES`. + + *Per-shell (does not survive new logins or reboot):* + + ``` + sudo prlimit --memlock=unlimited:unlimited --pid $$ + ulimit -l # confirm: prints 'unlimited' + ``` + + *Persistent (recommended; both edits needed because `systemd` and + PAM apply rlimits on different paths — `DefaultLimitMEMLOCK` only + reaches services systemd spawns directly, interactive shells go + through PAM):* + + ``` + # 1. systemd-spawned services + sudo sed -i 's|^#DefaultLimitMEMLOCK=.*|DefaultLimitMEMLOCK=infinity|' \ + /etc/systemd/system.conf + + # 2. PAM session limits (applied to login shells, sudo, etc.) + sudo tee /etc/security/limits.d/99-memlock.conf >/dev/null <<'EOF' + * soft memlock unlimited + * hard memlock unlimited + EOF + + # Apply: log out of every login shell and back in (no reboot needed). + # Verify in a new shell: + ulimit -l # → unlimited + cat /proc/$$/limits | grep "locked" # → unlimited / unlimited + ``` + + Matches the Zisk + [installation docs](https://0xpolygonhermez.github.io/zisk/getting_started/installation.html). + + **Heap cap.** The Zisk zkVM has a hard 512 MB RAM cap + ([`RAM_SIZE`](https://github.com/0xPolygonHermez/zisk/blob/v0.17.0/core/src/mem.rs#L111)), + of which ~510 MB is usable heap, and isn't configurable without + rebuilding the proving setup. Envs whose deserialized in-memory + representation exceeds that won't fit (full `TutorialDefs.lean` pulls in + Lean stdlib + Batteries + LSpec, around 1 GB resident). For bigger envs, + prefer the SP1 backend (default 24 GB runtime cap + [`DEFAULT_MEMORY_LIMIT`](https://github.com/succinctlabs/sp1/blob/v6.2.0/crates/core/executor/src/opts.rs#L25), + configurable via `MEMORY_LIMIT` env var up to a ~1 TB JIT ceiling + [`MAX_JIT_LOG_ADDR`](https://github.com/succinctlabs/sp1/blob/v6.2.0/crates/primitives/src/consts.rs#L11)), + or shrink the env via `--root ` to take the transitive closure of + a single constant. + + **Host RAM cap (`--max-witness-stored`).** Distinct from the in-guest + heap cap above, the prover side (Zisk's `proofman`) holds in-flight + witness traces in host RAM during `CALCULATING_CONTRIBUTIONS`. Peak + host RAM per shard ≈ `N × avg-witness-size + fixed overhead`, where + `N` is the `max_witness_stored` setting. The Ix kernel typecheck + workload averages ~25 GB per witness on typical 200–300 kB anon-byte + shards. + + The `zisk-host` CLI defaults to `--max-witness-stored 5` (Zisk's + built-in default is 10, tuned for larger-memory boxes). Override per + machine: + + | Host RAM | `--max-witness-stored` | Notes | + | -------- | ---------------------- | ------------------------------------------------------ | + | ≤ 128 GB | `3` | Override down; consider smaller shards too | + | 256 GB | `5` (project default) | Comfortable margin on the typical setup | + | 512 GB | `10` (Zisk default) | Override up for maximum prover parallelism | + | ≥ 1 TB | `10` (Zisk default) | Override up; default is conservative for this workload | + + Lowering the cap roughly linearly bounds peak RAM but throttles + prover parallelism (~10–30 % slower in practice). Raise it if your + machine has more RAM headroom; lower it if you OOM during + `CALCULATING_CONTRIBUTIONS`. Not relevant for `--execute` or + `--verify-constraints` modes. + ### Nix #### Prerequisites diff --git a/Tests/MinimalDefs.lean b/Tests/MinimalDefs.lean new file mode 100644 index 00000000..a83067cc --- /dev/null +++ b/Tests/MinimalDefs.lean @@ -0,0 +1,5 @@ +def myConst : Nat := 42 + +def myId (x : Nat) : Nat := x + +theorem myReflEq (n : Nat) : n = n := rfl diff --git a/crates/aiur/Cargo.toml b/crates/aiur/Cargo.toml new file mode 100644 index 00000000..c8d59ee0 --- /dev/null +++ b/crates/aiur/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "aiur" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +indexmap = { workspace = true } +multi-stark = { workspace = true } +rayon = { workspace = true } +rustc-hash = { workspace = true } +tracing = { workspace = true } +tracing-texray = { workspace = true } + +[features] +default = [] +parallel = ["multi-stark/parallel"] + +[lints] +workspace = true diff --git a/src/aiur/bytecode.rs b/crates/aiur/src/bytecode.rs similarity index 81% rename from src/aiur/bytecode.rs rename to crates/aiur/src/bytecode.rs index cb2769d1..927a3b40 100644 --- a/src/aiur/bytecode.rs +++ b/crates/aiur/src/bytecode.rs @@ -3,23 +3,23 @@ use crate::FxIndexMap; use super::G; pub struct Toplevel { - pub(crate) functions: Vec, - pub(crate) memory_sizes: Vec, + pub functions: Vec, + pub memory_sizes: Vec, } pub struct Function { - pub(crate) body: Block, - pub(crate) layout: FunctionLayout, - pub(crate) entry: bool, - pub(crate) constrained: bool, + pub body: Block, + pub layout: FunctionLayout, + pub entry: bool, + pub constrained: bool, } #[derive(Clone, Copy)] pub struct FunctionLayout { - pub(crate) input_size: usize, - pub(crate) selectors: usize, - pub(crate) auxiliaries: usize, - pub(crate) lookups: usize, + pub input_size: usize, + pub selectors: usize, + pub auxiliaries: usize, + pub lookups: usize, } impl FunctionLayout { @@ -29,8 +29,8 @@ impl FunctionLayout { } pub struct Block { - pub(crate) ops: Vec, - pub(crate) ctrl: Ctrl, + pub ops: Vec, + pub ctrl: Ctrl, } pub enum Op { diff --git a/src/aiur/constraints.rs b/crates/aiur/src/constraints.rs similarity index 97% rename from src/aiur/constraints.rs rename to crates/aiur/src/constraints.rs index abdbef2b..31de6387 100644 --- a/src/aiur/constraints.rs +++ b/crates/aiur/src/constraints.rs @@ -7,22 +7,19 @@ use multi_stark::{ use std::{array, ops::Range, sync::LazyLock}; use crate::{ - FxIndexMap, - aiur::{ - G, - bytecode::{Block, Ctrl, Function, FunctionLayout, Op, Toplevel, ValIdx}, - function_channel, - gadgets::{ - AiurGadget, - bytes1::{Bytes1, Bytes1Op}, - bytes2::{Bytes2, Bytes2Op}, - }, - memory_channel, u8_add_channel, u8_and_channel, - u8_bit_decomposition_channel, u8_chain_rotr4_channel, - u8_chain_rotr7_channel, u8_less_than_channel, u8_mul_channel, - u8_or_channel, u8_range_check_channel, u8_shift_left_channel, - u8_shift_right_channel, u8_sub_channel, u8_xor_channel, + FxIndexMap, G, + bytecode::{Block, Ctrl, Function, FunctionLayout, Op, Toplevel, ValIdx}, + function_channel, + gadgets::{ + AiurGadget, + bytes1::{Bytes1, Bytes1Op}, + bytes2::{Bytes2, Bytes2Op}, }, + memory_channel, u8_add_channel, u8_and_channel, u8_bit_decomposition_channel, + u8_chain_rotr4_channel, u8_chain_rotr7_channel, u8_less_than_channel, + u8_mul_channel, u8_or_channel, u8_range_check_channel, + u8_shift_left_channel, u8_shift_right_channel, u8_sub_channel, + u8_xor_channel, }; type Expr = SymbolicExpression; diff --git a/src/aiur/execute.rs b/crates/aiur/src/execute.rs similarity index 97% rename from src/aiur/execute.rs rename to crates/aiur/src/execute.rs index e28dae6e..cafd61bc 100644 --- a/src/aiur/execute.rs +++ b/crates/aiur/src/execute.rs @@ -3,28 +3,25 @@ use rustc_hash::FxHashMap; use std::collections::hash_map::Entry; use crate::{ - FxIndexMap, - aiur::{ - G, - bytecode::{Block, Ctrl, FunIdx, Function, Op, Toplevel}, - gadgets::{ - AiurGadget, - bytes1::{Bytes1, Bytes1Op, Bytes1Queries}, - bytes2::{Bytes2, Bytes2Op, Bytes2Queries}, - }, + FxIndexMap, G, + bytecode::{Block, Ctrl, FunIdx, Function, Op, Toplevel}, + gadgets::{ + AiurGadget, + bytes1::{Bytes1, Bytes1Op, Bytes1Queries}, + bytes2::{Bytes2, Bytes2Op, Bytes2Queries}, }, }; pub struct QueryResult { pub(crate) output: Vec, - pub(crate) multiplicity: G, + pub multiplicity: G, } pub type QueryMap = FxIndexMap, QueryResult>; pub struct QueryRecord { - pub(crate) function_queries: Vec, - pub(crate) memory_queries: FxIndexMap, + pub function_queries: Vec, + pub memory_queries: FxIndexMap, pub(crate) bytes1_queries: Bytes1Queries, pub(crate) bytes2_queries: Bytes2Queries, } @@ -44,17 +41,17 @@ impl QueryRecord { } } -pub(crate) struct IOKeyInfo { - pub(crate) idx: usize, - pub(crate) len: usize, +pub struct IOKeyInfo { + pub idx: usize, + pub len: usize, } pub struct IOBuffer { /// Per-channel data arenas. `idx` slots into `data[&channel]`. - pub(crate) data: FxHashMap>, + pub data: FxHashMap>, /// Channel-keyed info map; same `key` on different channels resolves /// to distinct `IOKeyInfo`. - pub(crate) map: FxHashMap<(G, Vec), IOKeyInfo>, + pub map: FxHashMap<(G, Vec), IOKeyInfo>, } impl IOBuffer { diff --git a/src/aiur/gadgets.rs b/crates/aiur/src/gadgets.rs similarity index 97% rename from src/aiur/gadgets.rs rename to crates/aiur/src/gadgets.rs index 2a3ca95f..a71c2b9d 100644 --- a/src/aiur/gadgets.rs +++ b/crates/aiur/src/gadgets.rs @@ -6,7 +6,7 @@ use multi_stark::{ p3_matrix::dense::RowMajorMatrix, }; -use crate::aiur::{G, execute::QueryRecord}; +use crate::{G, execute::QueryRecord}; /// A trait representing a generic Aiur gadget. /// diff --git a/src/aiur/gadgets/blake3.rs b/crates/aiur/src/gadgets/blake3.rs similarity index 99% rename from src/aiur/gadgets/blake3.rs rename to crates/aiur/src/gadgets/blake3.rs index 434f43b5..9fd508f9 100644 --- a/src/aiur/gadgets/blake3.rs +++ b/crates/aiur/src/gadgets/blake3.rs @@ -14,7 +14,7 @@ use multi_stark::{ p3_matrix::dense::RowMajorMatrix, }; -use crate::aiur::{ +use crate::{ G, execute::QueryRecord, gadgets::{ diff --git a/src/aiur/gadgets/bytes1.rs b/crates/aiur/src/gadgets/bytes1.rs similarity index 99% rename from src/aiur/gadgets/bytes1.rs rename to crates/aiur/src/gadgets/bytes1.rs index 1cc6525b..cc83c5c9 100644 --- a/src/aiur/gadgets/bytes1.rs +++ b/crates/aiur/src/gadgets/bytes1.rs @@ -6,7 +6,7 @@ use multi_stark::{ p3_matrix::dense::RowMajorMatrix, }; -use crate::aiur::{ +use crate::{ G, execute::QueryRecord, gadgets::AiurGadget, u8_bit_decomposition_channel, u8_shift_left_channel, u8_shift_right_channel, }; diff --git a/src/aiur/gadgets/bytes2.rs b/crates/aiur/src/gadgets/bytes2.rs similarity index 99% rename from src/aiur/gadgets/bytes2.rs rename to crates/aiur/src/gadgets/bytes2.rs index d8478aad..949dcff8 100644 --- a/src/aiur/gadgets/bytes2.rs +++ b/crates/aiur/src/gadgets/bytes2.rs @@ -6,7 +6,7 @@ use multi_stark::{ p3_matrix::dense::RowMajorMatrix, }; -use crate::aiur::{ +use crate::{ G, execute::QueryRecord, gadgets::AiurGadget, u8_add_channel, u8_and_channel, u8_chain_rotr4_channel, u8_chain_rotr7_channel, u8_less_than_channel, u8_mul_channel, u8_or_channel, u8_range_check_channel, u8_sub_channel, diff --git a/src/aiur.rs b/crates/aiur/src/lib.rs similarity index 91% rename from src/aiur.rs rename to crates/aiur/src/lib.rs index d54325cc..c0494edf 100644 --- a/src/aiur.rs +++ b/crates/aiur/src/lib.rs @@ -6,9 +6,12 @@ pub mod memory; pub mod synthesis; pub mod trace; +use indexmap::IndexMap; use multi_stark::p3_field::PrimeCharacteristicRing; +use rustc_hash::FxBuildHasher; pub type G = multi_stark::p3_goldilocks::Goldilocks; +pub type FxIndexMap = IndexMap; #[inline] pub const fn function_channel() -> G { diff --git a/src/aiur/memory.rs b/crates/aiur/src/memory.rs similarity index 98% rename from src/aiur/memory.rs rename to crates/aiur/src/memory.rs index fa676394..d6e74ff3 100644 --- a/src/aiur/memory.rs +++ b/crates/aiur/src/memory.rs @@ -13,7 +13,7 @@ use rayon::{ slice::ParallelSliceMut, }; -use crate::aiur::{G, execute::QueryRecord, memory_channel}; +use crate::{G, execute::QueryRecord, memory_channel}; pub struct Memory { width: usize, diff --git a/src/aiur/synthesis.rs b/crates/aiur/src/synthesis.rs similarity index 99% rename from src/aiur/synthesis.rs rename to crates/aiur/src/synthesis.rs index 1dd7f971..7d063593 100644 --- a/src/aiur/synthesis.rs +++ b/crates/aiur/src/synthesis.rs @@ -12,7 +12,7 @@ use rayon::iter::{ IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, }; -use crate::aiur::{ +use crate::{ G, bytecode::{FunIdx, Toplevel}, constraints::Constraints, diff --git a/src/aiur/trace.rs b/crates/aiur/src/trace.rs similarity index 97% rename from src/aiur/trace.rs rename to crates/aiur/src/trace.rs index df72f54d..48bd57d9 100644 --- a/src/aiur/trace.rs +++ b/crates/aiur/src/trace.rs @@ -11,20 +11,17 @@ use rayon::{ }; use crate::{ - FxIndexMap, - aiur::{ - G, - bytecode::{Block, Ctrl, Function, Op, Toplevel}, - execute::{IOBuffer, IOKeyInfo, QueryRecord}, - function_channel, - gadgets::{bytes1::Bytes1, bytes2::Bytes2}, - memory::Memory, - u8_add_channel, u8_and_channel, u8_bit_decomposition_channel, - u8_chain_rotr4_channel, u8_chain_rotr7_channel, u8_less_than_channel, - u8_mul_channel, u8_or_channel, u8_range_check_channel, - u8_shift_left_channel, u8_shift_right_channel, u8_sub_channel, - u8_xor_channel, - }, + FxIndexMap, G, + bytecode::{Block, Ctrl, Function, Op, Toplevel}, + execute::{IOBuffer, IOKeyInfo, QueryRecord}, + function_channel, + gadgets::{bytes1::Bytes1, bytes2::Bytes2}, + memory::Memory, + u8_add_channel, u8_and_channel, u8_bit_decomposition_channel, + u8_chain_rotr4_channel, u8_chain_rotr7_channel, u8_less_than_channel, + u8_mul_channel, u8_or_channel, u8_range_check_channel, + u8_shift_left_channel, u8_shift_right_channel, u8_sub_channel, + u8_xor_channel, }; struct ColumnIndex { diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml new file mode 100644 index 00000000..6ff7109c --- /dev/null +++ b/crates/common/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "ix-common" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +bignat = { workspace = true } +blake3 = { workspace = true } +indexmap = { workspace = true } +quickcheck = { workspace = true, optional = true } +rustc-hash = { workspace = true } + +[dev-dependencies] +quickcheck = { workspace = true } +quickcheck_macros = { workspace = true } + +[features] +quickcheck = ["dep:quickcheck"] + +[lints] +workspace = true diff --git a/src/ix/address.rs b/crates/common/src/address.rs similarity index 81% rename from src/ix/address.rs rename to crates/common/src/address.rs index df90d061..334aafd1 100644 --- a/src/ix/address.rs +++ b/crates/common/src/address.rs @@ -36,6 +36,23 @@ impl Address { self.hash.as_bytes() } + /// Flatten a slice of addresses into a `[u8; 32 * N]` byte blob. + pub fn pack(addrs: &[Address]) -> Vec { + let mut out = Vec::with_capacity(addrs.len() * 32); + for a in addrs { + out.extend_from_slice(a.as_bytes()); + } + out + } + + /// Iterate addresses out of a flat `[u8; 32 * N]` byte blob. Trailing + /// bytes shorter than 32 are silently dropped (via `chunks_exact`). + pub fn unpack(bytes: &[u8]) -> impl Iterator + '_ { + bytes + .chunks_exact(32) + .map(|c| Address::from_slice(c).expect("malformed address chunk")) + } + /// Build a deterministic, collision-resistant `Name` for this address: /// `Ix._#.`. Mirrors Lean-side `Ix.Address.toUniqueName`. /// @@ -43,8 +60,8 @@ impl Address { /// name that can't collide with any Lean-originated name (e.g. for /// scratch `KEnv` entries that should not participate in the /// `name_to_addr` / `aux_name_to_addr` namespace). - pub fn to_unique_name(&self) -> crate::ix::env::Name { - use crate::ix::env::Name; + pub fn to_unique_name(&self) -> crate::env::Name { + use crate::env::Name; Name::str( Name::str(Name::str(Name::anon(), "Ix".to_string()), "_#".to_string()), self.hex(), @@ -53,8 +70,8 @@ impl Address { /// Inverse of `to_unique_name`. Returns `Some(Address)` iff `name` has /// shape `Ix._#.` with valid 64-char hex; otherwise `None`. - pub fn from_unique_name(name: &crate::ix::env::Name) -> Option { - use crate::ix::env::NameData; + pub fn from_unique_name(name: &crate::env::Name) -> Option { + use crate::env::NameData; let (parent, hex) = match name.as_data() { NameData::Str(parent, s, _) => (parent.clone(), s.clone()), _ => return None, @@ -79,11 +96,8 @@ impl Address { /// Used by `compile/mutual.rs` to register each mutual block under a /// Muts-tagged meta so kernel ingress can discover and process it via /// `ingress_muts_block`. - pub fn muts_name( - &self, - first_member: &crate::ix::env::Name, - ) -> crate::ix::env::Name { - use crate::ix::env::{Name, NameData}; + pub fn muts_name(&self, first_member: &crate::env::Name) -> crate::env::Name { + use crate::env::{Name, NameData}; let base = Name::str(Name::str(Name::anon(), "Ix".to_string()), self.hex()); // Append each component of `first_member` to the base, preserving // numeric vs string parts. @@ -127,8 +141,8 @@ impl StdHash for Address { } } -#[cfg(test)] -pub mod tests { +#[cfg(any(test, feature = "quickcheck"))] +pub mod arbitrary { use super::*; use quickcheck::{Arbitrary, Gen}; diff --git a/src/ix/env.rs b/crates/common/src/env.rs similarity index 97% rename from src/ix/env.rs rename to crates/common/src/env.rs index ca700056..b2d6675a 100644 --- a/src/ix/env.rs +++ b/crates/common/src/env.rs @@ -14,7 +14,7 @@ use std::{ sync::Arc, }; -use lean_ffi::nat::Nat; +use bignat::Nat; use rustc_hash::FxHashMap; // -- Name tags ---------------------------------------------------------------- @@ -1464,3 +1464,51 @@ impl ConstantInfo { /// The Lean kernel environment: a map from names to their constant declarations. pub type Env = FxHashMap; + +#[cfg(any(test, feature = "quickcheck"))] +pub mod arbitrary { + use super::*; + use quickcheck::{Arbitrary, Gen}; + + impl Arbitrary for DefinitionSafety { + fn arbitrary(g: &mut Gen) -> Self { + match u8::arbitrary(g) % 3 { + 0 => DefinitionSafety::Unsafe, + 1 => DefinitionSafety::Safe, + _ => DefinitionSafety::Partial, + } + } + } + + impl Arbitrary for QuotKind { + fn arbitrary(g: &mut Gen) -> Self { + match u8::arbitrary(g) % 4 { + 0 => QuotKind::Type, + 1 => QuotKind::Ctor, + 2 => QuotKind::Lift, + _ => QuotKind::Ind, + } + } + } + + impl Arbitrary for BinderInfo { + fn arbitrary(g: &mut Gen) -> Self { + match u8::arbitrary(g) % 4 { + 0 => Self::Default, + 1 => Self::Implicit, + 2 => Self::StrictImplicit, + _ => Self::InstImplicit, + } + } + } + + impl Arbitrary for ReducibilityHints { + fn arbitrary(g: &mut Gen) -> Self { + match u8::arbitrary(g) % 3 { + 0 => Self::Opaque, + 1 => Self::Abbrev, + _ => Self::Regular(u32::arbitrary(g)), + } + } + } +} diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs new file mode 100644 index 00000000..e51d043c --- /dev/null +++ b/crates/common/src/lib.rs @@ -0,0 +1,21 @@ +//! Foundational types shared across the Ix project. +//! +//! Contains: +//! - `address`: 32-byte content-address newtype. +//! - `env`: the Lean kernel type representation (`Name`, `Level`, `Expr`, +//! `ConstantInfo`, `Env`, …) and the tag-byte constants used throughout. +//! - `mutual`: mutual-block helpers used by both compile and kernel. +//! - `strong_ordering`: small comparison helper. +//! +//! Plus the `FxIndexMap` / `FxIndexSet` aliases that the rest of the project +//! uses. + +use indexmap::{IndexMap, IndexSet}; +use rustc_hash::FxBuildHasher; + +pub mod address; +pub mod env; +pub mod strong_ordering; + +pub type FxIndexMap = IndexMap; +pub type FxIndexSet = IndexSet; diff --git a/src/ix/strong_ordering.rs b/crates/common/src/strong_ordering.rs similarity index 100% rename from src/ix/strong_ordering.rs rename to crates/common/src/strong_ordering.rs diff --git a/crates/compile/Cargo.toml b/crates/compile/Cargo.toml new file mode 100644 index 00000000..3fff593a --- /dev/null +++ b/crates/compile/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "ix-compile" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +anyhow = { workspace = true } +bignat = { workspace = true } +blake3 = { workspace = true } +dashmap = { workspace = true, features = ["rayon"] } +indexmap = { workspace = true, features = ["rayon"] } +itertools = { workspace = true } +ix-common = { workspace = true } +ixon = { workspace = true } +ix-kernel = { workspace = true } +num-bigint = { workspace = true } +rayon = { workspace = true } +rustc-hash = { workspace = true } +sha2 = { workspace = true } + +[lints] +workspace = true diff --git a/src/ix/compile.rs b/crates/compile/src/compile.rs similarity index 97% rename from src/ix/compile.rs rename to crates/compile/src/compile.rs index a16b2bc1..07949d77 100644 --- a/src/ix/compile.rs +++ b/crates/compile/src/compile.rs @@ -13,36 +13,38 @@ use std::{ sync::{Arc, atomic::Ordering as AtomicOrdering}, }; -use lean_ffi::nat::Nat; - -use crate::{ - ix::address::Address, - ix::env::{ - AxiomVal, BinderInfo, ConstantInfo as LeanConstantInfo, ConstructorVal, - DataValue as LeanDataValue, Env as LeanEnv, Expr as LeanExpr, ExprData, - InductiveVal, Level, LevelData, Literal, Name, NameData, QuotVal, - RecursorRule as LeanRecursorRule, SourceInfo as LeanSourceInfo, - Substring as LeanSubstring, Syntax as LeanSyntax, SyntaxPreresolved, +use bignat::Nat; + +use ix_common::address::Address; +use ix_common::env::{ + AxiomVal, BinderInfo, ConstantInfo as LeanConstantInfo, ConstructorVal, + DataValue as LeanDataValue, Env as LeanEnv, Expr as LeanExpr, ExprData, + InductiveVal, Level, LevelData, Literal, Name, NameData, QuotVal, + RecursorRule as LeanRecursorRule, SourceInfo as LeanSourceInfo, + Substring as LeanSubstring, Syntax as LeanSyntax, SyntaxPreresolved, +}; +use ix_common::strong_ordering::SOrd; + +use ixon::{ + CompileError, Tag0, + constant::{ + Axiom, Constant, ConstantInfo, Constructor, Definition, Inductive, + MutConst as IxonMutConst, Quotient, Recursor, RecursorRule, + ctor_proj_constant, defn_proj_constant, indc_proj_constant, + recr_proj_constant, }, - ix::graph::NameSet, - ix::ixon::{ - CompileError, Tag0, - constant::{ - Axiom, Constant, ConstantInfo, Constructor, Definition, Inductive, - MutConst as IxonMutConst, Quotient, Recursor, RecursorRule, - ctor_proj_constant, defn_proj_constant, indc_proj_constant, - recr_proj_constant, - }, - env::{Env as IxonEnv, Named}, - expr::Expr, - metadata::{ - ConstantMeta, ConstantMetaInfo, DataValue, ExprMeta, ExprMetaData, KVMap, - }, - sharing::{self, analyze_block, build_sharing_vec, decide_sharing}, - univ::Univ, + env::{Env as IxonEnv, Named}, + expr::Expr, + metadata::{ + ConstantMeta, ConstantMetaInfo, DataValue, ExprMeta, ExprMetaData, KVMap, }, - ix::mutual::{Def, Ind, MutConst, MutCtx, Rec, ctx_to_all}, - ix::strong_ordering::SOrd, + sharing::{self, analyze_block, build_sharing_vec, decide_sharing}, + univ::Univ, +}; + +use crate::{ + graph::NameSet, + mutual::{Def, Ind, MutConst, MutCtx, Rec, ctx_to_all}, }; /// Whether to track hash-consed sizes during compilation. @@ -87,7 +89,7 @@ pub struct KernelCtx { /// etc.) with aux-substituted types at `resolve_lean_name_addr`-derived /// addresses that may shift as alpha-collapse reassigns addresses over /// the course of compilation. - pub kenv: crate::ix::kernel::env::KEnv, + pub kenv: ix_kernel::env::KEnv, } impl Default for KernelCtx { @@ -98,7 +100,7 @@ impl Default for KernelCtx { impl KernelCtx { pub fn new() -> Self { - KernelCtx { kenv: crate::ix::kernel::env::KEnv::new() } + KernelCtx { kenv: ix_kernel::env::KEnv::new() } } } @@ -442,7 +444,7 @@ fn compile_univ_indices( fn univ_sort_key(univ: &Arc) -> Vec { let mut buf = Vec::new(); - crate::ix::ixon::univ::put_univ(univ, &mut buf); + ixon::univ::put_univ(univ, &mut buf); buf } @@ -540,7 +542,7 @@ fn collect_expr_tables( Ok(()) } -pub(crate) fn preseed_expr_tables( +pub fn preseed_expr_tables( exprs: &[(&LeanExpr, &[Name])], mut_ctx: &MutCtx, cache: &mut BlockCache, @@ -582,7 +584,7 @@ pub(crate) fn preseed_expr_tables( Ok(()) } -pub(crate) fn collect_mut_const_exprs<'a>( +pub fn collect_mut_const_exprs<'a>( cnst: &'a MutConst, exprs: &mut Vec<(&'a LeanExpr, &'a [Name])>, ) { @@ -621,7 +623,7 @@ pub fn compile_expr( cache: &mut BlockCache, stt: &CompileState, ) -> Result, CompileError> { - use crate::ix::ixon::metadata::CallSiteEntry; + use ixon::metadata::CallSiteEntry; // Stack-based iterative compilation to avoid stack overflow enum Frame { @@ -774,7 +776,7 @@ pub fn compile_expr( let compiling_is_aux_regen = cache .compiling .as_ref() - .is_some_and(crate::ix::decompile::is_aux_gen_suffix); + .is_some_and(crate::decompile::is_aux_gen_suffix); if !compiling_is_aux_regen { if let Some(plan) = stt.call_site_plans.get(name) && !plan.is_identity() @@ -1461,11 +1463,11 @@ fn compile_data_value(dv: &LeanDataValue, stt: &CompileState) -> DataValue { // Serialize Int and store as blob let mut bytes = Vec::new(); match i { - crate::ix::env::Int::OfNat(n) => { + ix_common::env::Int::OfNat(n) => { bytes.push(0); bytes.extend_from_slice(&n.to_le_bytes()); }, - crate::ix::env::Int::NegSucc(n) => { + ix_common::env::Int::NegSucc(n) => { bytes.push(1); bytes.extend_from_slice(&n.to_le_bytes()); }, @@ -1671,16 +1673,16 @@ fn apply_sharing(exprs: Vec>) -> (Vec>, Vec>) { } /// Result of applying sharing to a singleton constant. -pub(crate) struct SingletonSharingResult { +pub struct SingletonSharingResult { /// The compiled Constant - pub(crate) constant: Constant, + pub constant: Constant, /// Hash-consed size of expressions - pub(crate) hash_consed_size: usize, + pub hash_consed_size: usize, } /// Apply sharing to a Definition and return a Constant with stats. #[allow(clippy::needless_pass_by_value)] -pub(crate) fn apply_sharing_to_definition_with_stats( +pub fn apply_sharing_to_definition_with_stats( def: Definition, refs: Vec
, univs: Vec>, @@ -1704,7 +1706,7 @@ pub(crate) fn apply_sharing_to_definition_with_stats( /// Apply sharing to an Axiom and return a Constant with stats. #[allow(clippy::needless_pass_by_value)] -pub(crate) fn apply_sharing_to_axiom_with_stats( +pub fn apply_sharing_to_axiom_with_stats( ax: Axiom, refs: Vec
, univs: Vec>, @@ -1722,7 +1724,7 @@ pub(crate) fn apply_sharing_to_axiom_with_stats( /// Apply sharing to a Quotient and return a Constant with stats. #[allow(clippy::needless_pass_by_value)] -pub(crate) fn apply_sharing_to_quotient_with_stats( +pub fn apply_sharing_to_quotient_with_stats( quot: Quotient, refs: Vec
, univs: Vec>, @@ -1743,7 +1745,7 @@ pub(crate) fn apply_sharing_to_quotient_with_stats( } /// Apply sharing to a Recursor and return a Constant with stats. -pub(crate) fn apply_sharing_to_recursor_with_stats( +pub fn apply_sharing_to_recursor_with_stats( rec: Recursor, refs: Vec
, univs: Vec>, @@ -1780,15 +1782,15 @@ pub(crate) fn apply_sharing_to_recursor_with_stats( } /// Result of applying sharing to a mutual block. -pub(crate) struct MutualBlockSharingResult { +pub struct MutualBlockSharingResult { /// The compiled Constant - pub(crate) constant: Constant, + pub constant: Constant, /// Hash-consed size of all expressions in the block - pub(crate) hash_consed_size: usize, + pub hash_consed_size: usize, } /// Apply sharing to a mutual block and return a Constant with stats. -pub(crate) fn apply_sharing_to_mutual_block( +pub fn apply_sharing_to_mutual_block( mut_consts: Vec, refs: Vec
, univs: Vec>, @@ -1960,7 +1962,7 @@ enum MutConstKind { /// Compile a Definition. /// Arena persists across type + value within a constant. -pub(crate) fn compile_definition( +pub fn compile_definition( def: &Def, mut_ctx: &MutCtx, cache: &mut BlockCache, @@ -2031,7 +2033,7 @@ fn compile_recursor_rule( /// Compile a Recursor. /// Arena grows across type and all rule RHS expressions. -pub(crate) fn compile_recursor( +pub fn compile_recursor( rec: &Rec, mut_ctx: &MutCtx, cache: &mut BlockCache, @@ -2158,7 +2160,7 @@ fn compile_constructor( /// The inductive type gets its own arena. Each constructor gets its own arena /// via compile_constructor. No CtorMeta duplication — ConstantMeta::Indc only /// stores constructor name addresses. -pub(crate) fn compile_inductive( +pub fn compile_inductive( ind: &Ind, mut_ctx: &MutCtx, cache: &mut BlockCache, @@ -2315,20 +2317,20 @@ fn compile_quotient( // =========================================================================== /// Result of compiling a mutual block. -pub(crate) struct CompiledMutualBlock { +pub struct CompiledMutualBlock { /// The compiled Constant - pub(crate) constant: Constant, + pub constant: Constant, /// Content-addressed hash - pub(crate) addr: Address, + pub addr: Address, /// Hash-consed size (theoretical minimum with perfect DAG sharing) - pub(crate) hash_consed_size: usize, + pub hash_consed_size: usize, /// Serialized size (actual bytes) - pub(crate) serialized_size: usize, + pub serialized_size: usize, } /// Compile a mutual block with block-level sharing. /// Returns the Constant, its content-addressed hash, and size statistics. -pub(crate) fn compile_mutual_block( +pub fn compile_mutual_block( mut_consts: Vec, refs: Vec
, univs: Vec>, @@ -3890,18 +3892,18 @@ fn compile_mutual( .map(|r| r.clone()) } -pub(crate) mod aux_gen; +pub mod aux_gen; mod env; -pub(crate) mod mutual; -pub(crate) mod nat_conv; -pub(crate) mod surgery; +pub mod mutual; +pub mod nat_conv; +pub mod surgery; pub use env::{compile_env, compile_env_with_options}; #[cfg(test)] mod tests { use super::*; - use crate::ix::env::{BinderInfo, Expr as LeanExpr, Level}; - use crate::ix::ixon::metadata::CallSiteEntry; + use ix_common::env::{BinderInfo, Expr as LeanExpr, Level}; + use ixon::metadata::CallSiteEntry; #[test] fn test_compile_univ_zero() { @@ -4314,7 +4316,7 @@ mod tests { #[test] fn test_compile_axiom() { - use crate::ix::env::{AxiomVal, ConstantVal}; + use ix_common::env::{AxiomVal, ConstantVal}; // Create a simple axiom: axiom myAxiom : Type let name = Name::str(Name::anon(), "myAxiom".to_string()); @@ -4348,7 +4350,7 @@ mod tests { #[test] fn test_compile_simple_def() { - use crate::ix::env::{ + use ix_common::env::{ ConstantVal, DefinitionSafety, DefinitionVal, ReducibilityHints, }; @@ -4402,11 +4404,11 @@ mod tests { #[test] fn test_compile_self_referential_def() { - use crate::ix::env::{ + use ix_common::env::{ ConstantInfo as LeanConstantInfo, ConstantVal, DefinitionSafety, DefinitionVal, Env as LeanEnv, ReducibilityHints, }; - use crate::ix::ixon::constant::ConstantInfo; + use ixon::constant::ConstantInfo; // Create a self-referential definition (like a recursive function placeholder) // def myDef : Type := myDef (this is silly but tests the mutual handling) @@ -4462,7 +4464,7 @@ mod tests { #[test] fn test_compile_env_single_axiom() { - use crate::ix::env::{AxiomVal, ConstantVal}; + use ix_common::env::{AxiomVal, ConstantVal}; // Create a minimal environment with just one axiom let name = Name::str(Name::anon(), "myAxiom".to_string()); @@ -4484,7 +4486,7 @@ mod tests { #[test] fn test_compile_env_two_independent_axioms() { - use crate::ix::env::{AxiomVal, ConstantVal}; + use ix_common::env::{AxiomVal, ConstantVal}; let name1 = Name::str(Name::anon(), "axiom1".to_string()); let name2 = Name::str(Name::anon(), "axiom2".to_string()); @@ -4528,7 +4530,7 @@ mod tests { #[test] fn test_compile_env_def_referencing_axiom() { - use crate::ix::env::{ + use ix_common::env::{ AxiomVal, ConstantVal, DefinitionSafety, DefinitionVal, ReducibilityHints, }; @@ -4578,7 +4580,7 @@ mod tests { /// to the single representative in the Muts array. #[test] fn test_compile_mutual_alpha_equivalent_defs() { - use crate::ix::env::{ + use ix_common::env::{ ConstantVal, DefinitionSafety, DefinitionVal, ReducibilityHints, }; @@ -4656,7 +4658,7 @@ mod tests { /// with projections indexing correctly into the array. #[test] fn test_compile_mutual_alpha_equiv_with_different_third() { - use crate::ix::env::{ + use ix_common::env::{ ConstantVal, DefinitionSafety, DefinitionVal, ReducibilityHints, }; @@ -4765,8 +4767,8 @@ mod tests { #[test] fn test_mutual_block_roundtrip() { - use crate::ix::env::DefinitionSafety; - use crate::ix::ixon::constant::{DefKind, Definition}; + use ix_common::env::DefinitionSafety; + use ixon::constant::{DefKind, Definition}; // Create a mutual block and verify it roundtrips through serialization let sort0 = Expr::sort(0); @@ -4836,7 +4838,7 @@ mod tests { #[test] fn test_definition_with_sharing() { - use crate::ix::ixon::constant::{DefKind, Definition}; + use ixon::constant::{DefKind, Definition}; // Create a definition where typ and value share structure let sort0 = Expr::sort(0); @@ -4857,7 +4859,7 @@ mod tests { // Create constant with sharing at Constant level let def = Definition { kind: DefKind::Definition, - safety: crate::ix::env::DefinitionSafety::Safe, + safety: ix_common::env::DefinitionSafety::Safe, lvls: 0, typ: rewritten[0].clone(), value: rewritten[1].clone(), @@ -4880,7 +4882,7 @@ mod tests { #[test] fn test_axiom_with_sharing() { - use crate::ix::ixon::constant::Axiom; + use ixon::constant::Axiom; // Axiom with repeated subterms in its type let sort0 = Expr::sort(0); @@ -4915,7 +4917,7 @@ mod tests { #[test] fn test_recursor_with_sharing() { - use crate::ix::ixon::constant::{Recursor, RecursorRule}; + use ixon::constant::{Recursor, RecursorRule}; // Recursor with shared subterms across typ and rules let sort0 = Expr::sort(0); @@ -4981,7 +4983,7 @@ mod tests { #[test] fn test_inductive_with_sharing() { - use crate::ix::ixon::constant::{Constructor, Inductive}; + use ixon::constant::{Constructor, Inductive}; // Inductive with shared subterms across type and constructors let sort0 = Expr::sort(0); @@ -5091,8 +5093,8 @@ mod tests { #[test] fn test_roundtrip_axiom() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{AxiomVal, ConstantVal}; + use crate::decompile::decompile_env; + use ix_common::env::{AxiomVal, ConstantVal}; // Create an axiom: axiom myAxiom : Type let name = Name::str(Name::anon(), "myAxiom".to_string()); @@ -5125,8 +5127,8 @@ mod tests { #[test] fn test_roundtrip_axiom_with_level_params() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{AxiomVal, ConstantVal, Env as LeanEnv}; + use crate::decompile::decompile_env; + use ix_common::env::{AxiomVal, ConstantVal, Env as LeanEnv}; // Create an axiom with universe params: axiom myAxiom.{u, v} : Sort (max u v) let name = Name::str(Name::anon(), "myAxiom".to_string()); @@ -5168,8 +5170,8 @@ mod tests { #[test] fn test_roundtrip_definition() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ + use crate::decompile::decompile_env; + use ix_common::env::{ ConstantVal, DefinitionSafety, DefinitionVal, ReducibilityHints, }; @@ -5180,13 +5182,13 @@ mod tests { Name::str(Name::anon(), "x".to_string()), type1.clone(), type1.clone(), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); let value = LeanExpr::lam( Name::str(Name::anon(), "x".to_string()), type1, LeanExpr::bvar(Nat::from(0u64)), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); let def = DefinitionVal { cnst: ConstantVal { name: name.clone(), level_params: vec![], typ }, @@ -5221,8 +5223,8 @@ mod tests { #[test] fn test_roundtrip_def_referencing_axiom() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ + use crate::decompile::decompile_env; + use ix_common::env::{ AxiomVal, ConstantVal, DefinitionSafety, DefinitionVal, Env as LeanEnv, ReducibilityHints, }; @@ -5278,8 +5280,8 @@ mod tests { #[test] fn test_roundtrip_quotient() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ConstantVal, Env as LeanEnv, QuotKind, QuotVal}; + use crate::decompile::decompile_env; + use ix_common::env::{ConstantVal, Env as LeanEnv, QuotKind, QuotVal}; // Create quotient constants let quot_name = Name::str(Name::anon(), "Quot".to_string()); @@ -5298,9 +5300,9 @@ mod tests { Name::anon(), LeanExpr::bvar(Nat::from(1u64)), prop.clone(), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); let typ = LeanExpr::all( alpha, @@ -5309,9 +5311,9 @@ mod tests { Name::anon(), rel_type, sort_u.clone(), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); let quot = QuotVal { @@ -5348,8 +5350,8 @@ mod tests { #[test] fn test_roundtrip_theorem() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ConstantVal, Env as LeanEnv, TheoremVal}; + use crate::decompile::decompile_env; + use ix_common::env::{ConstantVal, Env as LeanEnv, TheoremVal}; // Create a theorem: theorem trivial : True := True.intro let name = Name::str(Name::anon(), "trivial".to_string()); @@ -5389,8 +5391,8 @@ mod tests { #[test] fn test_roundtrip_opaque() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ConstantVal, Env as LeanEnv, OpaqueVal}; + use crate::decompile::decompile_env; + use ix_common::env::{ConstantVal, Env as LeanEnv, OpaqueVal}; // Create an opaque: opaque secret : Nat := 42 let name = Name::str(Name::anon(), "secret".to_string()); @@ -5431,8 +5433,8 @@ mod tests { #[test] fn test_roundtrip_multiple_constants() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ + use crate::decompile::decompile_env; + use ix_common::env::{ AxiomVal, ConstantVal, DefinitionSafety, DefinitionVal, Env as LeanEnv, ReducibilityHints, TheoremVal, }; @@ -5506,8 +5508,8 @@ mod tests { #[test] fn test_roundtrip_inductive_simple() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ + use crate::decompile::decompile_env; + use ix_common::env::{ ConstantVal, ConstructorVal, Env as LeanEnv, InductiveVal, }; @@ -5589,8 +5591,8 @@ mod tests { #[test] fn test_roundtrip_inductive_with_multiple_ctors() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ + use crate::decompile::decompile_env; + use ix_common::env::{ ConstantVal, ConstructorVal, Env as LeanEnv, InductiveVal, }; @@ -5673,8 +5675,8 @@ mod tests { #[test] fn test_roundtrip_mutual_definitions() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ + use crate::decompile::decompile_env; + use ix_common::env::{ ConstantVal, DefinitionSafety, DefinitionVal, Env as LeanEnv, ReducibilityHints, }; @@ -5690,7 +5692,7 @@ mod tests { Name::anon(), type0.clone(), type0.clone(), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); // f := fun x => g x @@ -5701,7 +5703,7 @@ mod tests { LeanExpr::cnst(g_name.clone(), vec![]), LeanExpr::bvar(Nat::from(0u64)), ), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); // g := fun x => f x @@ -5712,7 +5714,7 @@ mod tests { LeanExpr::cnst(f_name.clone(), vec![]), LeanExpr::bvar(Nat::from(0u64)), ), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); // Mutual block: both reference each other @@ -5784,8 +5786,8 @@ mod tests { #[test] fn test_roundtrip_mutual_inductives() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ + use crate::decompile::decompile_env; + use ix_common::env::{ ConstantVal, ConstructorVal, Env as LeanEnv, InductiveVal, }; @@ -5855,7 +5857,7 @@ mod tests { Name::anon(), odd_type.clone(), even_type.clone(), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); let even_succ_ctor = ConstructorVal { @@ -5876,7 +5878,7 @@ mod tests { Name::anon(), even_type.clone(), odd_type.clone(), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); let odd_succ_ctor = ConstructorVal { @@ -5942,8 +5944,8 @@ mod tests { #[test] fn test_roundtrip_inductive_with_recursor() { - use crate::ix::decompile::decompile_env; - use crate::ix::env::{ConstantVal, InductiveVal, RecursorVal}; + use crate::decompile::decompile_env; + use ix_common::env::{ConstantVal, InductiveVal, RecursorVal}; // Create Empty type with recursor (no constructors) // inductive Empty : Type @@ -5976,7 +5978,7 @@ mod tests { Name::anon(), empty_type.clone(), LeanExpr::sort(Level::param(u.clone())), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); let rec_type = LeanExpr::all( Name::str(Name::anon(), "motive".to_string()), @@ -5988,9 +5990,9 @@ mod tests { LeanExpr::bvar(Nat::from(1u64)), LeanExpr::bvar(Nat::from(0u64)), ), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, ); let recursor = RecursorVal { diff --git a/src/ix/compile/aux_gen.rs b/crates/compile/src/compile/aux_gen.rs similarity index 96% rename from src/ix/compile/aux_gen.rs rename to crates/compile/src/compile/aux_gen.rs index 080a57e8..f9e06e5a 100644 --- a/src/ix/compile/aux_gen.rs +++ b/crates/compile/src/compile/aux_gen.rs @@ -74,28 +74,28 @@ //! - `.sparseCasesOn`, `.sparseCasesOnEq` //! - `.casesOnSameCtor`, `.casesOnSameCtorHet` -pub(crate) mod below; -pub(crate) mod brecon; -pub(crate) mod cases_on; -pub(crate) mod expr_utils; -pub(crate) mod nested; -pub(crate) mod rec_on; -pub(crate) mod recursor; +pub mod below; +pub mod brecon; +pub mod cases_on; +pub mod expr_utils; +pub mod nested; +pub mod rec_on; +pub mod recursor; use std::sync::Arc; use rustc_hash::FxHashMap; -use crate::ix::compile::CompileState; -use crate::ix::env::{ +use crate::compile::CompileState; +use ix_common::env::{ ConstantVal, Env as LeanEnv, Expr as LeanExpr, Name, RecursorRule, RecursorVal, }; -use crate::ix::ixon::CompileError; +use ixon::CompileError; /// A regenerated constant ready for compilation. #[derive(Clone)] -pub(crate) enum PatchedConstant { +pub enum PatchedConstant { /// A regenerated `.rec` recursor. Rec(RecursorVal), /// A regenerated `.recOn` definition (arg-reordered `.rec` wrapper). @@ -118,7 +118,7 @@ pub(crate) enum PatchedConstant { /// flips to `Unsafe` whenever the type or value mentions any unsafe constant — /// and every auxiliary references its parent inductive. #[derive(Clone)] -pub(crate) struct AuxDef { +pub struct AuxDef { pub name: Name, pub level_params: Vec, pub typ: LeanExpr, @@ -134,7 +134,7 @@ pub(crate) struct AuxDef { /// (to canonicalize Lean-source-order originals before structural /// comparison). #[derive(Clone, Default)] -pub(crate) struct AuxPatchesOutput { +pub struct AuxPatchesOutput { /// The regenerated canonical-layout constants, keyed by their /// Lean-visible source-indexed name (e.g. `A.rec`, `A.below_2`). pub patches: FxHashMap, @@ -185,12 +185,12 @@ pub(crate) struct AuxPatchesOutput { /// `InductiveVal.all` of any block member). It determines the canonical /// `.rec_N` naming and the source-aux walk used to compute the /// hash-sort permutation. -pub(crate) fn generate_aux_patches( +pub fn generate_aux_patches( sorted_classes: &[Vec], original_all: &[Name], lean_env: &Arc, stt: &CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + kctx: &mut crate::compile::KernelCtx, ) -> Result { let mut patches: FxHashMap = FxHashMap::default(); let mut aliases: FxHashMap = FxHashMap::default(); @@ -257,8 +257,8 @@ pub(crate) fn generate_aux_patches( let metadata_has_nested = original_all.iter().any(|name| { matches!( lean_env.get(name), - Some(crate::ix::env::ConstantInfo::InductInfo(v)) - if crate::ix::compile::nat_conv::nat_to_usize(&v.num_nested) > 0 + Some(ix_common::env::ConstantInfo::InductInfo(v)) + if crate::compile::nat_conv::nat_to_usize(&v.num_nested) > 0 ) }); let (canonical_recs, is_prop) = if metadata_has_nested @@ -529,7 +529,7 @@ pub(crate) fn generate_aux_patches( for (rec_name, rec_val) in canonical_recs.iter().take(n_classes) { // Build casesOn name: rec_name is "I.rec", casesOn name is "I.casesOn" let ind_name = match rec_name.as_data() { - crate::ix::env::NameData::Str(parent, _, _) => parent.clone(), + ix_common::env::NameData::Str(parent, _, _) => parent.clone(), _ => continue, }; let cases_on_name = Name::str(ind_name, "casesOn".to_string()); @@ -549,7 +549,7 @@ pub(crate) fn generate_aux_patches( // types (unlike below_N/brecOn_N which ARE generated via BRecOn.lean). for (rec_name, rec_val) in canonical_recs.iter().take(n_classes) { let ind_name = match rec_name.as_data() { - crate::ix::env::NameData::Str(parent, _, _) => parent.clone(), + ix_common::env::NameData::Str(parent, _, _) => parent.clone(), _ => continue, }; let rec_on_name = Name::str(ind_name, "recOn".to_string()); @@ -650,7 +650,7 @@ pub(crate) fn generate_aux_patches( .and_then(|c| c.first()) .map(|n| n.pretty()) .unwrap_or_default(); - if *crate::ix::compile::IX_TIMING + if *crate::compile::IX_TIMING && _below_elapsed.as_secs_f32() + _brecon_elapsed.as_secs_f32() > 0.3 { eprintln!( @@ -669,7 +669,7 @@ pub(crate) fn generate_aux_patches( .and_then(|c| c.first()) .map(|n| n.pretty()) .unwrap_or_default(); - if *crate::ix::compile::IX_TIMING && _p1_elapsed.as_secs_f32() > 0.5 { + if *crate::compile::IX_TIMING && _p1_elapsed.as_secs_f32() > 0.5 { eprintln!( "[gen_patches] {:?} recGen={:.2}s patches={}", _gen_label, @@ -721,13 +721,13 @@ pub(crate) fn generate_aux_patches( ) { let rep_ctors = match lean_env.get(rep) { - Some(crate::ix::env::ConstantInfo::InductInfo(v)) => { + Some(ix_common::env::ConstantInfo::InductInfo(v)) => { v.ctors.clone() }, _ => vec![], }; let alias_ctors = match lean_env.get(alias) { - Some(crate::ix::env::ConstantInfo::InductInfo(v)) => { + Some(ix_common::env::ConstantInfo::InductInfo(v)) => { v.ctors.clone() }, _ => vec![], @@ -896,7 +896,7 @@ pub(crate) fn generate_aux_patches( /// This distinguishes `.below` auxiliaries from coincidental name collisions /// like structure field accessors (e.g., `NewDecl.below : NewDecl → LocalDecl`). fn is_below_shaped(typ: &LeanExpr) -> bool { - use crate::ix::env::ExprData; + use ix_common::env::ExprData; let mut cur = typ; loop { match cur.as_data() { @@ -914,16 +914,16 @@ fn is_below_shaped(typ: &LeanExpr) -> bool { /// and may differ from the originals in `lean_env`. The canonical TC /// (`stt.canon_tc`) uses `canon_kenv` exclusively, so it sees the /// correct types for PProd(motive, I.below ...) inference. -pub(crate) fn populate_canon_kenv_with_below( +pub fn populate_canon_kenv_with_below( below_consts: &[below::BelowConstant], sorted_classes: &[Vec], - lean_env: &crate::ix::env::Env, + lean_env: &ix_common::env::Env, stt: &CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + kctx: &mut crate::compile::KernelCtx, ) { - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::ingress::{ + use ix_kernel::constant::KConst; + use ix_kernel::id::KId; + use ix_kernel::ingress::{ lean_expr_to_zexpr_with_kenv, resolve_lean_name_addr, }; @@ -965,9 +965,9 @@ pub(crate) fn populate_canon_kenv_with_below( KConst::Defn { name: d.name.clone(), level_params: d.level_params.clone(), - kind: crate::ix::ixon::constant::DefKind::Definition, - safety: crate::ix::env::DefinitionSafety::Safe, - hints: crate::ix::env::ReducibilityHints::Abbrev, + kind: ixon::constant::DefKind::Definition, + safety: ix_common::env::DefinitionSafety::Safe, + hints: ix_common::env::ReducibilityHints::Abbrev, lvls: d.level_params.len() as u64, ty: ty_z, val: val_z, diff --git a/src/ix/compile/aux_gen/below.rs b/crates/compile/src/compile/aux_gen/below.rs similarity index 98% rename from src/ix/compile/aux_gen/below.rs rename to crates/compile/src/compile/aux_gen/below.rs index a483e83f..407dc5e7 100644 --- a/src/ix/compile/aux_gen/below.rs +++ b/crates/compile/src/compile/aux_gen/below.rs @@ -8,12 +8,12 @@ //! //! Follows `refs/lean4/src/Lean/Meta/Constructions/BRecOn.lean:59-108`. -use crate::ix::compile::nat_conv::{nat_to_usize, try_nat_to_usize}; -use crate::ix::env::{ +use crate::compile::nat_conv::{nat_to_usize, try_nat_to_usize}; +use ix_common::env::{ BinderInfo, ConstantInfo, ConstructorVal, Env as LeanEnv, Expr as LeanExpr, ExprData, InductiveVal, Level, LevelData, Name, RecursorVal, }; -use crate::ix::ixon::CompileError; +use ixon::CompileError; use super::expr_utils::{ LocalDecl, decompose_apps, find_motive_fvar, forall_telescope, fresh_fvar, @@ -38,7 +38,7 @@ pub(super) fn aux_rec_suffix_idx(aux_rec_name: &Name) -> Option { /// A generated `.below` constant — either a definition (Type-level) /// or an inductive (Prop-level). #[derive(Clone)] -pub(crate) enum BelowConstant { +pub enum BelowConstant { /// Type-level `.below`: a reducible definition using `.rec` + PProd. Def(BelowDef), /// Prop-level `.below`: an inductive type with constructors. @@ -53,7 +53,7 @@ pub(crate) enum BelowConstant { /// type or value references an unsafe constant — for unsafe inductives this /// always triggers because `.below` mentions the parent inductive's `.rec`. #[derive(Clone)] -pub(crate) struct BelowDef { +pub struct BelowDef { pub name: Name, pub level_params: Vec, pub typ: LeanExpr, @@ -63,7 +63,7 @@ pub(crate) struct BelowDef { /// A generated `.below` inductive (Prop-level case). #[derive(Clone)] -pub(crate) struct BelowIndc { +pub struct BelowIndc { pub name: Name, pub level_params: Vec, pub n_params: usize, @@ -87,7 +87,7 @@ pub(crate) struct BelowIndc { /// A constructor for a Prop-level `.below` inductive. #[derive(Clone)] -pub(crate) struct BelowCtor { +pub struct BelowCtor { pub name: Name, pub typ: LeanExpr, pub n_params: usize, @@ -107,13 +107,13 @@ pub(crate) struct BelowCtor { /// Note: `is_prop` is distinct from `is_large`. A Prop inductive with single /// constructors and all-Prop fields gets large elimination (`drec`), but Lean /// still generates `.below` as an inductive via `IndPredBelow`. -pub(crate) fn generate_below_constants( +pub fn generate_below_constants( sorted_classes: &[Vec], canonical_recs: &[(Name, RecursorVal)], lean_env: &LeanEnv, is_prop: bool, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result, CompileError> { let n_classes = sorted_classes.len(); if n_classes == 0 || canonical_recs.is_empty() { @@ -262,7 +262,7 @@ pub(crate) fn generate_below_constants( /// Build a single `.below` definition for a Type-level inductive. /// /// The `.below` definition's value is: -/// ``` +/// ```text /// λ {params} {motives} (indices) (major), /// I.rec.{succ(rlvl), lvls...} params /// (λ (indices) (major), Sort rlvl) -- for each motive @@ -276,8 +276,8 @@ fn build_below_def( lean_env: &LeanEnv, n_classes: usize, canonical_recs: &[(Name, RecursorVal)], - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result { let n_params = try_nat_to_usize(&rec_val.num_params)?; let n_motives = try_nat_to_usize(&rec_val.num_motives)?; @@ -475,8 +475,8 @@ fn build_below_value( rlvl: &Level, _n_classes: usize, _canonical_recs: &[(Name, RecursorVal)], - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result { let n_params = try_nat_to_usize(&rec_val.num_params)?; let n_motives = try_nat_to_usize(&rec_val.num_motives)?; @@ -1687,10 +1687,10 @@ fn mk_imax_aux(l1: &Level, l2: &Level) -> Level { /// Uses raw `Level::succ` / `Level::max` to faithfully preserve the kernel's /// level structure — no distribution of Succ over Max, no subsumption. pub(super) fn kuniv_to_level( - u: &crate::ix::kernel::level::KUniv, + u: &ix_kernel::level::KUniv, param_names: &[Name], ) -> Level { - use crate::ix::kernel::level::UnivData; + use ix_kernel::level::UnivData; match u.data() { UnivData::Zero(_) => Level::zero(), UnivData::Succ(inner, _) => Level::succ(kuniv_to_level(inner, param_names)), @@ -1774,7 +1774,7 @@ pub(super) fn mk_punit_unit(lvl: &Level) -> LeanExpr { /// Used when extracting motive domains from the recursor type for Prop-level /// `.below` inductives. The recursor may have large elimination (extra `u` /// param), but `.below` motives always target Prop. -pub(crate) fn replace_result_sort_with_prop(expr: &LeanExpr) -> LeanExpr { +pub fn replace_result_sort_with_prop(expr: &LeanExpr) -> LeanExpr { match expr.as_data() { ExprData::ForallE(name, dom, body, bi, _) => LeanExpr::all( name.clone(), diff --git a/src/ix/compile/aux_gen/brecon.rs b/crates/compile/src/compile/aux_gen/brecon.rs similarity index 98% rename from src/ix/compile/aux_gen/brecon.rs rename to crates/compile/src/compile/aux_gen/brecon.rs index dff154d8..fdcd0582 100644 --- a/src/ix/compile/aux_gen/brecon.rs +++ b/crates/compile/src/compile/aux_gen/brecon.rs @@ -8,13 +8,13 @@ //! `.brecOn.go` uses PProd-wrapped motives; `.brecOn` projects first component. //! Reference: `refs/lean4/src/Lean/Meta/Constructions/BRecOn.lean:191-308` -use crate::ix::compile::nat_conv::try_nat_to_usize; -use crate::ix::env::{ +use crate::compile::nat_conv::try_nat_to_usize; +use bignat::Nat; +use ix_common::env::{ BinderInfo, ConstantInfo, Env as LeanEnv, Expr as LeanExpr, ExprData, InductiveVal, Level, LevelData, Name, RecursorVal, }; -use crate::ix::ixon::CompileError; -use lean_ffi::nat::Nat; +use ixon::CompileError; use super::below::{ BelowConstant, mk_level_succ, mk_pprod, mk_pprod_mk, mk_punit_unit, @@ -44,7 +44,7 @@ use rustc_hash::FxHashMap; /// `.brecOn.eq`. `.go` and `.brecOn` are always `Defn`; `.eq` is `Thm` /// (safe) or unsafe `Defn` with `hints := .opaque`. #[derive(Clone)] -pub(crate) struct BRecOnDef { +pub struct BRecOnDef { pub name: Name, pub level_params: Vec, pub typ: LeanExpr, @@ -59,14 +59,14 @@ pub(crate) struct BRecOnDef { /// from Phase 1 and the `.below` constants from Phase 2. /// `is_prop` determines whether to generate Prop-level (single theorem) or /// Type-level (`.brecOn.go` + `.brecOn`) forms. -pub(crate) fn generate_brecon_constants( +pub fn generate_brecon_constants( sorted_classes: &[Vec], canonical_recs: &[(Name, RecursorVal)], below_consts: &[BelowConstant], lean_env: &LeanEnv, is_prop: bool, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result, CompileError> { let n_classes = sorted_classes.len(); if n_classes == 0 || canonical_recs.is_empty() || below_consts.is_empty() { @@ -623,8 +623,8 @@ fn build_type_brecon_fvar( below_names: &[Name], lean_env: &LeanEnv, n_classes: usize, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result, CompileError> { // canon_kenv is populated by `populate_canon_kenv_with_below` in // aux_gen.rs between Phase 2 and Phase 3. It contains PUnit, PProd, @@ -1076,16 +1076,15 @@ fn build_type_brecon_fvar( }, ]; - if let Some((eq_typ, eq_val)) = eq_result { - results.push(BRecOnDef { - name: eq_name, - level_params: rec_level_params.clone(), - typ: eq_typ, - value: eq_val, - is_unsafe, - is_prop: false, - }); - } + let (eq_typ, eq_val) = eq_result; + results.push(BRecOnDef { + name: eq_name, + level_params: rec_level_params.clone(), + typ: eq_typ, + value: eq_val, + is_unsafe, + is_prop: false, + }); Ok(results) } @@ -1441,18 +1440,14 @@ fn build_type_brecon_eq_fvar( // `Eq` and `HEq` binders in `motive_wrapped` and // `build_minor_via_cases_sim`'s remaining list. rec_level_params: &[Name], - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, -) -> Option<(LeanExpr, LeanExpr)> { - // .brecOn.eq requires Eq and Eq.refl as constants. In the full pipeline, - // aux_gen is only called when the original Lean environment has these - // constants, so this always succeeds. But in minimal test environments - // (e.g., unit tests with synthetic inductives), Eq may not exist. - // Return None in that case — matching the old BVar code's behavior. - // - // TODO: Accept a lean_env parameter and check lean_env.get("Eq").is_some() - // for a more principled guard. For now, we always generate .eq since the - // real pipeline guarantees Eq exists. + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, +) -> (LeanExpr, LeanExpr) { + // .brecOn.eq requires Eq and Eq.refl as constants. The real pipeline only + // calls aux_gen when the original Lean environment has these, so this + // always succeeds. If a future minimal-test caller needs to opt out (e.g. + // a synthetic inductive without Eq), reintroduce an `Option` return or + // gate via a `lean_env.get("Eq").is_some()` check. let _ = n_minors; let _n_motives = motive_fvars.len(); @@ -1577,7 +1572,7 @@ fn build_type_brecon_eq_fvar( kctx, ); if let Some(eq_value) = eq_value_opt { - return Some((eq_type, eq_value)); + return (eq_type, eq_value); } // Fall through to the simple path if the indexed construction // couldn't be completed (e.g., missing ctor info). @@ -1717,7 +1712,7 @@ fn build_type_brecon_eq_fvar( let eq_value = mk_lambda(eq_val, all_decls); - Some((eq_type, eq_value)) + (eq_type, eq_value) } // ========================================================================= @@ -1785,8 +1780,8 @@ fn build_indexed_eq_value( // `Eq` and `HEq` binders (matching Lean's `mkEqAndProof` in // `refs/lean4/src/Lean/Meta/Tactic/Cases.lean:30-37`). rec_level_params: &[Name], - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Option { let n_indices = index_decls.len(); let outer_major = &major_fvars[0]; diff --git a/src/ix/compile/aux_gen/cases_on.rs b/crates/compile/src/compile/aux_gen/cases_on.rs similarity index 98% rename from src/ix/compile/aux_gen/cases_on.rs rename to crates/compile/src/compile/aux_gen/cases_on.rs index 4d2ec2e7..b14a4163 100644 --- a/src/ix/compile/aux_gen/cases_on.rs +++ b/crates/compile/src/compile/aux_gen/cases_on.rs @@ -10,8 +10,8 @@ //! //! Follows `refs/lean4/src/library/constructions/cases_on.cpp`. -use crate::ix::compile::aux_gen::AuxDef; -use crate::ix::env::{ +use crate::compile::aux_gen::AuxDef; +use ix_common::env::{ BinderInfo, ConstantInfo, Env as LeanEnv, Expr as LeanExpr, ExprData, Level, Name, RecursorVal, }; @@ -53,7 +53,7 @@ fn mk_pi_unit(e: &LeanExpr, unit: &LeanExpr) -> LeanExpr { /// Uses FVar-based construction: opens the rec type into FVars, builds /// casesOn type and value using FVar references, then abstracts with /// mk_forall/mk_lambda. -pub(crate) fn generate_cases_on( +pub fn generate_cases_on( name: &Name, rec_val: &RecursorVal, lean_env: &LeanEnv, @@ -65,7 +65,7 @@ pub(crate) fn generate_cases_on( // Extract target inductive name from "A.casesOn" → "A" let target_ind = match name.as_data() { - crate::ix::env::NameData::Str(parent, s, _) if s == "casesOn" => { + ix_common::env::NameData::Str(parent, s, _) if s == "casesOn" => { parent.clone() }, _ => return None, @@ -370,8 +370,8 @@ fn get_minor_name( #[cfg(test)] mod tests { use super::*; - use crate::ix::env::{BinderInfo, ConstantVal, InductiveVal, Literal}; - use lean_ffi::nat::Nat; + use bignat::Nat; + use ix_common::env::{BinderInfo, ConstantVal, InductiveVal, Literal}; fn mk_name_for(s: &str) -> Name { let mut n = Name::anon(); diff --git a/src/ix/compile/aux_gen/expr_utils.rs b/crates/compile/src/compile/aux_gen/expr_utils.rs similarity index 96% rename from src/ix/compile/aux_gen/expr_utils.rs rename to crates/compile/src/compile/aux_gen/expr_utils.rs index 986dc6f0..92105974 100644 --- a/src/ix/compile/aux_gen/expr_utils.rs +++ b/crates/compile/src/compile/aux_gen/expr_utils.rs @@ -9,14 +9,14 @@ use rustc_hash::{FxHashMap, FxHashSet}; -use crate::ix::address::Address; -use crate::ix::compile::nat_conv::{nat_to_u64, nat_to_usize}; -use crate::ix::env::{ +use crate::compile::nat_conv::{nat_to_u64, nat_to_usize}; +use bignat::Nat; +use ix_common::address::Address; +use ix_common::env::{ BinderInfo, Expr as LeanExpr, ExprData, Level, LevelData, Name, }; -use crate::ix::kernel::ingress::{lean_level_to_kuniv, resolve_lean_name_addr}; -use crate::ix::kernel::mode::Meta; -use lean_ffi::nat::Nat; +use ix_kernel::ingress::{lean_level_to_kuniv, resolve_lean_name_addr}; +use ix_kernel::mode::Meta; // ========================================================================= // FVar infrastructure @@ -28,7 +28,7 @@ use lean_ffi::nat::Nat; /// FVar space. The `fvar_name` is a unique identifier; `binder_name` is /// the cosmetic name that appears in the final forall/lambda chain. #[derive(Clone)] -pub(crate) struct LocalDecl { +pub struct LocalDecl { pub fvar_name: Name, pub binder_name: Name, pub domain: LeanExpr, @@ -36,7 +36,7 @@ pub(crate) struct LocalDecl { } /// Create a fresh FVar with a unique name derived from `prefix` and `idx`. -pub(crate) fn fresh_fvar(prefix: &str, idx: usize) -> (Name, LeanExpr) { +pub fn fresh_fvar(prefix: &str, idx: usize) -> (Name, LeanExpr) { let name = Name::str(Name::anon(), format!("_{}_{}", prefix, idx)); let fvar = LeanExpr::fvar(name.clone()); (name, fvar) @@ -119,13 +119,13 @@ pub(super) struct IndRecInfo { /// loop body and terminates peeling, potentially yielding a shorter /// `indices` vec than Lean's stored `num_indices`. pub(super) fn decompose_inductive_type( - ind: &crate::ix::env::InductiveVal, + ind: &ix_common::env::InductiveVal, ind_univs: &[Level], param_fvars: &[LocalDecl], - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, -) -> Result { - use crate::ix::ixon::CompileError; + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, +) -> Result { + use ixon::CompileError; let n_params = param_fvars.len(); let ty = subst_levels(&ind.cnst.typ, &ind.cnst.level_params, ind_univs); @@ -274,7 +274,7 @@ pub(super) fn decompose_inductive_type( /// position MUST verify `decls.len() == n` before indexing — otherwise /// a surprising input shape becomes a panic. Prefer /// [`forall_telescope_exact`] when a precise arity is required. -pub(crate) fn forall_telescope( +pub fn forall_telescope( expr: &LeanExpr, n: usize, prefix: &str, @@ -322,10 +322,7 @@ pub(super) fn forall_telescope_exact( start_idx: usize, context: &str, what: &str, -) -> Result< - (Vec, Vec, LeanExpr), - crate::ix::ixon::CompileError, -> { +) -> Result<(Vec, Vec, LeanExpr), ixon::CompileError> { let (fvars, decls, body) = forall_telescope(expr, n, prefix, start_idx); if decls.len() != n { // Include enough context to pinpoint the shape problem: every peeled @@ -337,7 +334,7 @@ pub(super) fn forall_telescope_exact( format!("{}:{}", d.binder_name.pretty(), describe_expr_head(&d.domain)) }) .collect(); - return Err(crate::ix::ixon::CompileError::UnsupportedExpr { + return Err(ixon::CompileError::UnsupportedExpr { desc: format!( "{context}: expected {n} leading foralls ({what}), got {actual}. \ Peeled binders (name:domain_kind): [{binders}]. \ @@ -447,7 +444,7 @@ pub(super) fn mk_forall(body: LeanExpr, binders: &[LocalDecl]) -> LeanExpr { /// Build a lambda chain by batch-abstracting all FVars in a single pass. /// /// Same semantics as `mk_forall` but produces `λ (x : T), body`. -pub(crate) fn mk_lambda(body: LeanExpr, binders: &[LocalDecl]) -> LeanExpr { +pub fn mk_lambda(body: LeanExpr, binders: &[LocalDecl]) -> LeanExpr { mk_binder_chain(body, binders, BinderKind::Lambda) } @@ -601,10 +598,7 @@ pub(super) fn batch_abstract( /// /// `instantiate1` is used when peeling forall binders during recursor /// construction (matching Lean C++ and lean4lean). -pub(crate) fn instantiate1( - body: &LeanExpr, - replacement: &LeanExpr, -) -> LeanExpr { +pub fn instantiate1(body: &LeanExpr, replacement: &LeanExpr) -> LeanExpr { instantiate1_at(body, replacement, 0) } @@ -862,7 +856,7 @@ pub(super) fn shift_vars( // ========================================================================= /// Substitute universe parameters in expressions. -pub(crate) fn subst_levels( +pub fn subst_levels( expr: &LeanExpr, params: &[Name], univs: &[Level], @@ -1259,7 +1253,7 @@ impl<'a> RestoreState<'a> { } /// Open lambda binders into FVars (matching forall_telescope but for lambdas). -pub(crate) fn lambda_telescope( +pub fn lambda_telescope( expr: &LeanExpr, n: usize, prefix: &str, @@ -1490,7 +1484,7 @@ pub(super) fn mk_const(name: &Name, univs: &[Level]) -> LeanExpr { /// /// Called by the kernel's `mk_local_decl` during inductive processing /// to ensure parameter/field types are clean before entering the local context. -pub(crate) fn consume_type_annotations(e: &LeanExpr) -> LeanExpr { +pub fn consume_type_annotations(e: &LeanExpr) -> LeanExpr { let (head, args) = decompose_apps(e); if let ExprData::Const(name, _, _) = head.as_data() { let n = name.pretty(); @@ -1507,7 +1501,7 @@ pub(crate) fn consume_type_annotations(e: &LeanExpr) -> LeanExpr { } /// Decompose an application spine: `f a1 a2 ... an` -> `(f, [a1, ..., an])`. -pub(crate) fn decompose_apps(expr: &LeanExpr) -> (LeanExpr, Vec) { +pub fn decompose_apps(expr: &LeanExpr) -> (LeanExpr, Vec) { let mut args = Vec::new(); let mut cur = expr.clone(); while let ExprData::App(f, a, _) = cur.as_data() { @@ -1724,14 +1718,14 @@ pub(super) fn find_motive_fvar( /// ``` /// Ensure PUnit and PProd are in the given kenv for kernel type inference. /// Accepts `kctx` so callers can choose which KernelCtx to populate. -pub(crate) fn ensure_prelude_in_kenv_of( - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, +pub fn ensure_prelude_in_kenv_of( + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) { - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::expr::KExpr; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::level::KUniv; + use ix_kernel::constant::KConst; + use ix_kernel::expr::KExpr; + use ix_kernel::id::KId; + use ix_kernel::level::KUniv; let n2a = Some(&stt.name_to_addr); let aux_n2a = Some(&stt.aux_name_to_addr); @@ -1950,17 +1944,15 @@ pub(crate) fn ensure_prelude_in_kenv_of( /// requires the parent). fn ensure_in_kenv_of_inner_env( name: &Name, - lean_env: &crate::ix::env::Env, - stt: &crate::ix::compile::CompileState, - kenv: &mut crate::ix::kernel::env::KEnv, + lean_env: &ix_common::env::Env, + stt: &crate::compile::CompileState, + kenv: &mut ix_kernel::env::KEnv, replace_axio_stub: bool, ) { - use crate::ix::env::{ConstantInfo as LCI, DefinitionSafety}; - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::ingress::{ - lean_expr_to_zexpr_cached, param_names_hash, - }; + use ix_common::env::{ConstantInfo as LCI, DefinitionSafety}; + use ix_kernel::constant::KConst; + use ix_kernel::id::KId; + use ix_kernel::ingress::{lean_expr_to_zexpr_cached, param_names_hash}; let n2a = Some(&stt.name_to_addr); let aux_n2a = Some(&stt.aux_name_to_addr); @@ -1982,10 +1974,10 @@ fn ensure_in_kenv_of_inner_env( // Helper: convert a LeanExpr to KExpr with the given level param names, // using the KEnv's persistent ingress cache. Callers are top-level, so // we start with an empty binder-name stack. - let to_z = |expr: &crate::ix::env::Expr, + let to_z = |expr: &ix_common::env::Expr, lp: &[Name], - kenv: &mut crate::ix::kernel::env::KEnv| - -> crate::ix::kernel::expr::KExpr { + kenv: &mut ix_kernel::env::KEnv| + -> ix_kernel::expr::KExpr { let pn_h = param_names_hash(lp); let mut binder_names: Vec = Vec::new(); lean_expr_to_zexpr_cached( @@ -2059,7 +2051,7 @@ fn ensure_in_kenv_of_inner_env( KConst::Defn { name: name.clone(), level_params: lp.clone(), - kind: crate::ix::ixon::constant::DefKind::Definition, + kind: ixon::constant::DefKind::Definition, safety: d.safety, hints: d.hints, lvls: lp.len() as u64, @@ -2079,9 +2071,9 @@ fn ensure_in_kenv_of_inner_env( KConst::Defn { name: name.clone(), level_params: lp.clone(), - kind: crate::ix::ixon::constant::DefKind::Theorem, + kind: ixon::constant::DefKind::Theorem, safety: DefinitionSafety::Safe, - hints: crate::ix::env::ReducibilityHints::Opaque, + hints: ix_common::env::ReducibilityHints::Opaque, lvls: lp.len() as u64, ty, val, @@ -2099,9 +2091,9 @@ fn ensure_in_kenv_of_inner_env( KConst::Defn { name: name.clone(), level_params: lp.clone(), - kind: crate::ix::ixon::constant::DefKind::Opaque, + kind: ixon::constant::DefKind::Opaque, safety: DefinitionSafety::Safe, - hints: crate::ix::env::ReducibilityHints::Opaque, + hints: ix_common::env::ReducibilityHints::Opaque, lvls: lp.len() as u64, ty, val, @@ -2157,9 +2149,9 @@ fn ensure_in_kenv_of_inner_env( fn ensure_in_kenv_of_inner( name: &Name, - lean_env: &crate::ix::env::Env, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + lean_env: &ix_common::env::Env, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, replace_axio_stub: bool, ) { ensure_in_kenv_of_inner_env( @@ -2171,11 +2163,11 @@ fn ensure_in_kenv_of_inner( ); } -pub(crate) fn ensure_in_kenv_of( +pub fn ensure_in_kenv_of( name: &Name, - lean_env: &crate::ix::env::Env, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + lean_env: &ix_common::env::Env, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) { ensure_in_kenv_of_inner(name, lean_env, stt, kctx, false); } @@ -2183,30 +2175,30 @@ pub(crate) fn ensure_in_kenv_of( /// Like [`ensure_in_kenv_of`], but upgrades an existing type-only `Axio` /// stub into the real constant. This is required before WHNF paths that must /// unfold reducible definitions or inspect inductive/ctor metadata. -pub(crate) fn ensure_full_in_kenv_of( +pub fn ensure_full_in_kenv_of( name: &Name, - lean_env: &crate::ix::env::Env, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + lean_env: &ix_common::env::Env, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) { ensure_in_kenv_of_inner(name, lean_env, stt, kctx, true); } fn ensure_full_in_tc_env( name: &Name, - lean_env: &crate::ix::env::Env, - stt: &crate::ix::compile::CompileState, - kenv: &mut crate::ix::kernel::env::KEnv, + lean_env: &ix_common::env::Env, + stt: &crate::compile::CompileState, + kenv: &mut ix_kernel::env::KEnv, ) { ensure_in_kenv_of_inner_env(name, lean_env, stt, kenv, true); } /// Convenience wrapper: ingress into the **original** kenv (`stt.kctx`). -pub(crate) fn ensure_in_kenv( +pub fn ensure_in_kenv( name: &Name, - lean_env: &crate::ix::env::Env, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + lean_env: &ix_common::env::Env, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) { ensure_in_kenv_of(name, lean_env, stt, kctx); } @@ -2224,8 +2216,8 @@ pub(super) struct TcScope<'a> { fvar_levels: FxHashMap, base_depth: usize, param_names: &'a [Name], - stt: &'a crate::ix::compile::CompileState, - tc: crate::ix::kernel::tc::TypeChecker<'a, Meta>, + stt: &'a crate::compile::CompileState, + tc: ix_kernel::tc::TypeChecker<'a, Meta>, /// How many extra locals are currently pushed above base_depth. extra_locals: usize, } @@ -2235,8 +2227,8 @@ impl<'a> TcScope<'a> { pub(super) fn new( outer_fvar_ctx: &[LocalDecl], param_names: &'a [Name], - stt: &'a crate::ix::compile::CompileState, - kctx: &'a mut crate::ix::compile::KernelCtx, + stt: &'a crate::compile::CompileState, + kctx: &'a mut crate::compile::KernelCtx, ) -> Self { let fvar_levels: FxHashMap = outer_fvar_ctx .iter() @@ -2244,7 +2236,7 @@ impl<'a> TcScope<'a> { .map(|(i, decl)| (decl.fvar_name.clone(), i)) .collect(); - let mut tc = crate::ix::kernel::tc::TypeChecker::new(&mut kctx.kenv); + let mut tc = ix_kernel::tc::TypeChecker::new(&mut kctx.kenv); tc.infer_only = true; // Push outer FVar types once. @@ -2347,9 +2339,9 @@ impl<'a> TcScope<'a> { fn get_level_error( &self, ty: &LeanExpr, - kexpr: &crate::ix::kernel::expr::KExpr, - e: &crate::ix::kernel::error::TcError, - ) -> crate::ix::ixon::CompileError { + kexpr: &ix_kernel::expr::KExpr, + e: &ix_kernel::error::TcError, + ) -> ixon::CompileError { eprintln!("[TcScope::get_level] FAILED"); eprintln!(" lean_expr: {}", ty.pretty()); eprintln!(" kexpr: {kexpr}"); @@ -2361,10 +2353,10 @@ impl<'a> TcScope<'a> { self.extra_locals ); // Dump kenv entries for constants referenced in the expression. - let mut stack: Vec<&crate::ix::kernel::expr::KExpr> = vec![kexpr]; + let mut stack: Vec<&ix_kernel::expr::KExpr> = vec![kexpr]; let mut seen_ids = std::collections::HashSet::new(); while let Some(expr) = stack.pop() { - use crate::ix::kernel::expr::ExprData as ZED; + use ix_kernel::expr::ExprData as ZED; match expr.data() { ZED::Const(id, us, _) => { if seen_ids.insert(id.clone()) { @@ -2391,7 +2383,7 @@ impl<'a> TcScope<'a> { _ => {}, } } - crate::ix::ixon::CompileError::UnsupportedExpr { + ixon::CompileError::UnsupportedExpr { desc: format!( "TcScope::get_level({}): tc.infer failed: {e}", ty.pretty() @@ -2412,7 +2404,7 @@ impl<'a> TcScope<'a> { pub(super) fn get_level( &mut self, ty: &LeanExpr, - ) -> Result { + ) -> Result { // Fast path: read Sort level from stored type (matching Lean's // inferAppType which peels foralls without substituting term args). // Sort levels use level params, not BVars, so the level is correct @@ -2432,14 +2424,14 @@ impl<'a> TcScope<'a> { let inferred = loop { match self.tc.infer(&kexpr) { Ok(inferred) => break inferred, - Err(crate::ix::kernel::error::TcError::UnknownConst(addr)) + Err(ix_kernel::error::TcError::UnknownConst(addr)) if faulted_addrs.insert(addr.clone()) && self.fault_in_addr(&addr) => {}, Err(e) => return Err(self.get_level_error(ty, &kexpr, &e)), } }; let ku = self.tc.ensure_sort(&inferred).map_err(|e| { - crate::ix::ixon::CompileError::UnsupportedExpr { + ixon::CompileError::UnsupportedExpr { desc: format!("TcScope::get_level: ensure_sort failed: {e}"), } })?; @@ -2463,7 +2455,7 @@ impl<'a> TcScope<'a> { /// Check if a Level is guaranteed non-zero. Matches Lean's `is_not_zero`: /// true for Succ(_), Param, Max(a,b) where either is not-zero. fn is_not_zero_level(l: &Level) -> bool { - use crate::ix::env::LevelData; + use ix_common::env::LevelData; match l.as_data() { LevelData::Succ(_, _) => true, LevelData::Max(a, b, _) => { @@ -2484,8 +2476,8 @@ impl<'a> TcScope<'a> { /// application, not enough foralls, result isn't Sort, or the constant /// isn't found in the kernel env). fn try_infer_app_sort_level(&self, ty: &LeanExpr) -> Option { - use crate::ix::env::ExprData; - use crate::ix::kernel::expr::ExprData as ZED; + use ix_common::env::ExprData; + use ix_kernel::expr::ExprData as ZED; // Decompose into head constant + args. let (head, args) = decompose_apps(ty); @@ -2498,7 +2490,7 @@ impl<'a> TcScope<'a> { let n2a = Some(&self.stt.name_to_addr); let aux_n2a = Some(&self.stt.aux_name_to_addr); let addr = resolve_lean_name_addr(name, n2a, aux_n2a); - let kid = crate::ix::kernel::id::KId::new(addr, name.clone()); + let kid = ix_kernel::id::KId::new(addr, name.clone()); let kconst = self.tc.env.get(&kid)?; let kty = kconst.ty(); @@ -2535,10 +2527,10 @@ impl<'a> TcScope<'a> { /// the concrete levels from a Const's level args. fn kuniv_to_level_with_const_levels( &self, - u: &crate::ix::kernel::level::KUniv, + u: &ix_kernel::level::KUniv, const_levels: &[Level], ) -> Level { - use crate::ix::kernel::level::UnivData; + use ix_kernel::level::UnivData; match u.data() { UnivData::Zero(_) => Level::zero(), UnivData::Succ(inner, _) => { @@ -2681,13 +2673,13 @@ impl<'a> TcScope<'a> { /// `Mdata` layers carried by the kernel expression are re-wrapped around /// the result in original order — matching `egress_expr`. pub(super) fn kexpr_to_lean( - expr: &crate::ix::kernel::expr::KExpr, + expr: &ix_kernel::expr::KExpr, outer_depth: usize, fvar_levels: &FxHashMap, local_depth: usize, param_names: &[Name], ) -> LeanExpr { - use crate::ix::kernel::expr::ExprData as KED; + use ix_kernel::expr::ExprData as KED; // Reverse `fvar_levels` lazily via linear search — the FVar context is // small in practice (a handful of param/motive/minor/index binders), @@ -2772,11 +2764,11 @@ pub(super) fn kexpr_to_lean( kexpr_to_lean(val, outer_depth, fvar_levels, local_depth, param_names), ), KED::Nat(n, _, _) => { - use crate::ix::env::Literal; + use ix_common::env::Literal; LeanExpr::lit(Literal::NatVal(n.clone())) }, KED::Str(s, _, _) => { - use crate::ix::env::Literal; + use ix_common::env::Literal; LeanExpr::lit(Literal::StrVal(s.clone())) }, }; @@ -2805,8 +2797,8 @@ fn collect_lean_source_name_hints( fvar_levels: &FxHashMap, depth: usize, param_names: &[Name], - stt: &crate::ix::compile::CompileState, - out: &mut FxHashMap, + stt: &crate::compile::CompileState, + out: &mut FxHashMap, ) { if source_name_hint_candidate(source) && !expr_has_bvar(source) { let key = @@ -2909,8 +2901,8 @@ fn restore_lean_source_name_hints( fvar_levels: &FxHashMap, depth: usize, param_names: &[Name], - stt: &crate::ix::compile::CompileState, - hints: &FxHashMap, + stt: &crate::compile::CompileState, + hints: &FxHashMap, ) -> LeanExpr { if source_name_hint_candidate(generated) && !expr_has_bvar(generated) { let key = to_kexpr_static(generated, fvar_levels, depth, param_names, stt) @@ -3061,7 +3053,7 @@ fn expr_has_bvar(expr: &LeanExpr) -> bool { fn restore_source_names_same_content( generated: &LeanExpr, source: &LeanExpr, - stt: &crate::ix::compile::CompileState, + stt: &crate::compile::CompileState, ) -> LeanExpr { let source = strip_mdata_ref(source); @@ -3077,7 +3069,7 @@ fn restore_source_names_same_content( fn restore_source_names_same_content_inner( generated: &LeanExpr, source: &LeanExpr, - stt: &crate::ix::compile::CompileState, + stt: &crate::compile::CompileState, ) -> LeanExpr { match (generated.as_data(), source.as_data()) { ( @@ -3146,7 +3138,7 @@ fn strip_mdata_ref(mut expr: &LeanExpr) -> &LeanExpr { fn same_resolved_name_addr( a: &Name, b: &Name, - stt: &crate::ix::compile::CompileState, + stt: &crate::compile::CompileState, ) -> bool { if a == b { return true; @@ -3167,13 +3159,13 @@ fn to_kexpr_static( fvar_levels: &FxHashMap, ctx_depth: usize, param_names: &[Name], - stt: &crate::ix::compile::CompileState, -) -> crate::ix::kernel::expr::KExpr { + stt: &crate::compile::CompileState, +) -> ix_kernel::expr::KExpr { let n2a = Some(&stt.name_to_addr); let aux_n2a = Some(&stt.aux_name_to_addr); - use crate::ix::kernel::expr::KExpr; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::level::KUniv; + use ix_kernel::expr::KExpr; + use ix_kernel::id::KId; + use ix_kernel::level::KUniv; match expr.as_data() { ExprData::Fvar(fname, _) => { @@ -3225,7 +3217,7 @@ fn to_kexpr_static( KExpr::prj(zid, nat_to_u64(idx), ke) }, ExprData::Lit(lit, _) => { - use crate::ix::env::Literal; + use ix_common::env::Literal; match lit { Literal::NatVal(n) => { let addr = Address::hash(&nat_to_u64(n).to_le_bytes()); @@ -3277,7 +3269,7 @@ fn collect_lean_const_refs(expr: &LeanExpr, out: &mut FxHashSet) { #[cfg(test)] mod tests { use super::*; - use crate::ix::env::BinderInfo; + use ix_common::env::BinderInfo; fn mk_name_for(s: &str) -> Name { let mut n = Name::anon(); @@ -3654,7 +3646,7 @@ mod tests { fn consume_type_annotations_strips_known_wrappers() { // `outParam α` reduces to `α`. We use a stub inductive name that the // function recognizes. - use crate::ix::env::BinderInfo; + use ix_common::env::BinderInfo; let inner = sort0(); let wrapped = LeanExpr::app( LeanExpr::cnst(mk_name_for("outParam"), vec![]), diff --git a/src/ix/compile/aux_gen/nested.rs b/crates/compile/src/compile/aux_gen/nested.rs similarity index 98% rename from src/ix/compile/aux_gen/nested.rs rename to crates/compile/src/compile/aux_gen/nested.rs index 726f70a1..5a57d2c2 100644 --- a/src/ix/compile/aux_gen/nested.rs +++ b/crates/compile/src/compile/aux_gen/nested.rs @@ -14,26 +14,26 @@ //! - Spec_params are built in FVar space during detection, then abstracted back //! to BVars for the returned `CompileFlatMember`. +use bignat::Nat; use blake3::Hash; -use lean_ffi::nat::Nat; use rustc_hash::{FxHashMap, FxHashSet}; use super::expr_utils::{ LocalDecl, batch_abstract, decompose_apps, forall_telescope, instantiate_pi_params, instantiate1, mk_forall, subst_levels, }; -use crate::ix::compile::nat_conv::{nat_to_u64, nat_to_usize}; -use crate::ix::env::{ +use crate::compile::nat_conv::{nat_to_u64, nat_to_usize}; +use ix_common::env::{ ConstantInfo, Env as LeanEnv, Expr as LeanExpr, ExprData, Level, Name, }; -use crate::ix::ixon::CompileError; +use ixon::CompileError; /// A member of the flat block (original inductive or nested auxiliary). /// /// Spec_params use BVars relative to the block's parameter context: /// `BVar(0)` = innermost (last) param, `BVar(n_params-1)` = outermost (first). #[derive(Clone)] -pub(crate) struct CompileFlatMember { +pub struct CompileFlatMember { pub name: Name, pub spec_params: Vec, pub occurrence_level_args: Vec, @@ -51,7 +51,7 @@ pub(crate) struct CompileFlatMember { /// Matches the C++ kernel's `elim_nested_inductive_result`: auxiliary types /// like `_nested.Array_1` replace `Array (Part α β)` so that the recursor /// generator can treat all members uniformly. -pub(crate) struct ExpandedBlock { +pub struct ExpandedBlock { /// All types in the expanded block: originals first, then auxiliaries. pub types: Vec, /// `aux_name → nested_expr`: the original nested application with block @@ -82,7 +82,7 @@ pub(crate) struct ExpandedBlock { /// All members share the same `level_params` and `n_params` — auxiliaries /// have the block's parameters, not the external inductive's own parameters. #[derive(Clone)] -pub(crate) struct ExpandedMember { +pub struct ExpandedMember { /// Inductive name: original name for originals, `_nested.ExtInd_N` for /// auxiliaries (scoped under `all[0]`). pub name: Name, @@ -101,7 +101,7 @@ pub(crate) struct ExpandedMember { /// A constructor in the expanded block. #[derive(Clone)] -pub(crate) struct ExpandedCtor { +pub struct ExpandedCtor { /// Constructor name: for auxiliaries, prefixed with aux name. pub name: Name, /// Constructor type with nested refs replaced by aux const applications. @@ -424,7 +424,7 @@ impl<'a> ExpandCtx<'a> { /// /// Matches the C++ kernel's `elim_nested_inductive_fn::operator()()` at /// `refs/lean4/src/kernel/inductive.cpp:1045-1077`. -pub(crate) fn expand_nested_block( +pub fn expand_nested_block( ordered_originals: &[Name], lean_env: &LeanEnv, alias_to_rep: &FxHashMap, @@ -612,9 +612,9 @@ pub(crate) fn expand_nested_block( /// appear in user-visible env: `RestoreCtx` converts them back to /// `ExtInd spec_params` expressions during recursor emission. So renaming /// them by canonical index is purely an internal-labeling change. -pub(crate) fn sort_aux_by_partition_refinement( +pub fn sort_aux_by_partition_refinement( expanded: &mut ExpandedBlock, - stt: &crate::ix::compile::CompileState, + stt: &crate::compile::CompileState, ) -> Result, CompileError> { let n_originals = expanded.n_originals; let n_total = expanded.types.len(); @@ -629,9 +629,9 @@ pub(crate) fn sort_aux_by_partition_refinement( // fixed positional MutRef, so alpha-equivalent originals collapse to the same // aux signature. If any referenced original is unresolved, compare_expr now // errors instead of falling back to namespace-sensitive name hashes. - use crate::ix::compile::{BlockCache, sort_consts}; - use crate::ix::env::{ConstantVal, ConstructorVal, InductiveVal}; - use crate::ix::mutual::{Ind, MutConst}; + use crate::compile::{BlockCache, sort_consts}; + use crate::mutual::{Ind, MutConst}; + use ix_common::env::{ConstantVal, ConstructorVal, InductiveVal}; let level_params = expanded.level_params.clone(); @@ -780,7 +780,7 @@ pub(crate) fn sort_aux_by_partition_refinement( let nested_prefix = { let first_aux_name = &expanded.types[n_originals].name; match first_aux_name.as_data() { - crate::ix::env::NameData::Str(prefix, _, _) => prefix.clone(), + ix_common::env::NameData::Str(prefix, _, _) => prefix.clone(), _ => { return Err(CompileError::InvalidMutualBlock { reason: format!( @@ -806,7 +806,7 @@ pub(crate) fn sort_aux_by_partition_refinement( // Extract the "" identifier from old suffix. let ext_name = match old_name.as_data() { - crate::ix::env::NameData::Str(_, suffix, _) => { + ix_common::env::NameData::Str(_, suffix, _) => { // Old suffix is "_" — strip the trailing "_". let s: &str = suffix.as_ref(); // Find the last underscore — everything before is "". @@ -940,7 +940,7 @@ pub(crate) fn sort_aux_by_partition_refinement( /// /// `original_all` is the source-order Lean `InductiveVal.all` list — /// not alpha-collapsed representatives, and not canonical-aux-sorted. -pub(crate) fn source_aux_order( +pub fn source_aux_order( original_all: &[Name], lean_env: &LeanEnv, ) -> Result)>, CompileError> { @@ -954,7 +954,7 @@ pub(crate) fn source_aux_order( /// Like [`source_aux_order`], but also reports the source mutual-block member /// whose constructor walk first discovered each auxiliary. -pub(crate) fn source_aux_order_with_owner( +pub fn source_aux_order_with_owner( original_all: &[Name], lean_env: &LeanEnv, ) -> Result)>, CompileError> { @@ -990,7 +990,7 @@ fn source_aux_order_from_expanded( /// source auxes whose spec_params reference inductives that belong to /// a different SCC block — those auxes are handled by that block's /// compilation, not ours. -pub(crate) const PERM_OUT_OF_SCC: usize = usize::MAX; +pub const PERM_OUT_OF_SCC: usize = usize::MAX; /// Compute the permutation mapping Lean-source aux-walk positions to /// canonical aux positions. Returns `perm: Vec` @@ -1024,11 +1024,11 @@ pub(crate) const PERM_OUT_OF_SCC: usize = usize::MAX; /// Returns an error if some canonical aux has no matching source. This /// shouldn't happen because canonical members are always a subset (via /// dedup) of what a full source walk would find. -pub(crate) fn compute_aux_perm( +pub fn compute_aux_perm( expanded: &ExpandedBlock, original_all: &[Name], lean_env: &LeanEnv, - stt: &crate::ix::compile::CompileState, + stt: &crate::compile::CompileState, orig_to_canon_names: &std::collections::HashMap, ) -> Result, CompileError> { let n_originals = expanded.n_originals; @@ -1208,12 +1208,12 @@ pub(crate) fn compute_aux_perm( fn aux_spec_eq( canon: &LeanExpr, src: &LeanExpr, - stt: &crate::ix::compile::CompileState, + stt: &crate::compile::CompileState, source_to_canon_fvar: &FxHashMap, cache: &mut FxHashMap<(Hash, Hash), bool>, ) -> bool { - let canon = crate::ix::congruence::strip_mdata(canon); - let src = crate::ix::congruence::strip_mdata(src); + let canon = crate::congruence::strip_mdata(canon); + let src = crate::congruence::strip_mdata(src); let key = (*canon.get_hash(), *src.get_hash()); if let Some(cached) = cache.get(&key) { @@ -1226,7 +1226,7 @@ fn aux_spec_eq( source_to_canon_fvar.get(b).map_or(a == b, |expected| a == expected) }, (ExprData::Sort(a, _), ExprData::Sort(b, _)) => { - crate::ix::congruence::level_alpha_eq(a, b).is_ok() + crate::congruence::level_alpha_eq(a, b).is_ok() }, ( ExprData::Const(a_name, a_lvls, _), @@ -1236,7 +1236,7 @@ fn aux_spec_eq( || a_lvls .iter() .zip(b_lvls.iter()) - .any(|(a, b)| crate::ix::congruence::level_alpha_eq(a, b).is_err()) + .any(|(a, b)| crate::congruence::level_alpha_eq(a, b).is_err()) { return false; } @@ -1669,7 +1669,7 @@ struct FvarFlatMember { /// caught by checking for non-param FVars in the detected spec_params. /// /// Ported from the kernel's `build_flat_block` (`src/ix/kernel/inductive.rs:364-475`). -pub(crate) fn build_compile_flat_block( +pub fn build_compile_flat_block( ordered_originals: &[Name], lean_env: &LeanEnv, ) -> Result, CompileError> { @@ -1680,7 +1680,7 @@ pub(crate) fn build_compile_flat_block( /// environment first for all lookups. Used by the expand/restore path /// to scan expanded constructor types (where nested refs are already /// replaced with auxiliary const applications). -pub(crate) fn build_compile_flat_block_with_overlay( +pub fn build_compile_flat_block_with_overlay( ordered_originals: &[Name], lean_env: &LeanEnv, overlay: Option<&LeanEnv>, @@ -1905,7 +1905,7 @@ fn abstract_spec_params_to_bvars( /// This function computes the pointwise max of `occurrence_level_args` across /// all auxiliaries with the same `name`, then updates all of them. fn maximize_occurrence_levels(flat: &mut [FvarFlatMember], n_originals: usize) { - use crate::ix::env::LevelData; + use ix_common::env::LevelData; use rustc_hash::FxHashMap; // Group auxiliary members by external inductive name. @@ -2080,10 +2080,10 @@ fn try_detect_nested_fvar( #[cfg(test)] mod tests { use super::*; - use crate::ix::env::{ + use bignat::Nat; + use ix_common::env::{ AxiomVal, ConstantVal, InductiveVal, Level as LL, Name, }; - use lean_ffi::nat::Nat; fn mk_name_for(s: &str) -> Name { let mut n = Name::anon(); @@ -2134,7 +2134,7 @@ mod tests { mk_name_for("x"), sort0(), LeanExpr::cnst(mk_name_for("Target"), vec![]), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); assert!(expr_mentions_any_name(&e, &names_of([mk_name_for("Target")]))); } @@ -2219,7 +2219,7 @@ mod tests { mk_name_for("x"), sort0(), LeanExpr::bvar(Nat::from(0u64)), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); assert!(!has_invalid_spec_ref(&e, &[])); } @@ -2231,7 +2231,7 @@ mod tests { mk_name_for("x"), sort0(), LeanExpr::fvar(unknown), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ); assert!(has_invalid_spec_ref(&e, &[])); } @@ -2285,7 +2285,7 @@ mod tests { mk_name_for("_"), LeanExpr::cnst(nat_name.clone(), vec![]), LeanExpr::cnst(nat_name.clone(), vec![]), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, ), }, is_unsafe: false, diff --git a/src/ix/compile/aux_gen/rec_on.rs b/crates/compile/src/compile/aux_gen/rec_on.rs similarity index 97% rename from src/ix/compile/aux_gen/rec_on.rs rename to crates/compile/src/compile/aux_gen/rec_on.rs index eec09eaa..2bc934a9 100644 --- a/src/ix/compile/aux_gen/rec_on.rs +++ b/crates/compile/src/compile/aux_gen/rec_on.rs @@ -7,8 +7,8 @@ //! the FVar/declaration arrays, then close back with mk_forall/mk_lambda. //! Follows `refs/lean4/src/Lean/Meta/Constructions/RecOn.lean`. -use crate::ix::compile::aux_gen::AuxDef; -use crate::ix::env::{Level, Name, RecursorVal}; +use crate::compile::aux_gen::AuxDef; +use ix_common::env::{Level, Name, RecursorVal}; use super::expr_utils::{ forall_telescope, mk_app_n, mk_const, mk_forall, mk_lambda, @@ -17,10 +17,7 @@ use super::expr_utils::{ /// Generate a `.recOn` definition from a canonical `.rec`. /// /// Returns `None` if the recursor type cannot be decomposed. -pub(crate) fn generate_rec_on( - name: &Name, - rec_val: &RecursorVal, -) -> Option { +pub fn generate_rec_on(name: &Name, rec_val: &RecursorVal) -> Option { let n_params = rec_val.num_params.to_u64()? as usize; let n_motives = rec_val.num_motives.to_u64()? as usize; let n_minors = rec_val.num_minors.to_u64()? as usize; @@ -79,8 +76,8 @@ pub(crate) fn generate_rec_on( #[cfg(test)] mod tests { use super::*; - use crate::ix::env::{BinderInfo, ConstantVal, Expr as LeanExpr, ExprData}; - use lean_ffi::nat::Nat; + use bignat::Nat; + use ix_common::env::{BinderInfo, ConstantVal, Expr as LeanExpr, ExprData}; fn mk_name(s: &str) -> Name { Name::str(Name::anon(), s.to_string()) diff --git a/src/ix/compile/aux_gen/recursor.rs b/crates/compile/src/compile/aux_gen/recursor.rs similarity index 96% rename from src/ix/compile/aux_gen/recursor.rs rename to crates/compile/src/compile/aux_gen/recursor.rs index c5c51539..6c8924b6 100644 --- a/src/ix/compile/aux_gen/recursor.rs +++ b/crates/compile/src/compile/aux_gen/recursor.rs @@ -11,16 +11,14 @@ //! Key difference from C++: we use FVar-based intermediate computation //! (see `expr_utils.rs`) then abstract back into de Bruijn binder chains. -use crate::ix::compile::nat_conv::{ - nat_to_u64, nat_to_usize, try_nat_to_usize, -}; -use crate::ix::env::{ +use crate::compile::nat_conv::{nat_to_u64, nat_to_usize, try_nat_to_usize}; +use bignat::Nat; +use ix_common::env::{ BinderInfo, ConstantInfo, ConstantVal, ConstructorVal, Env as LeanEnv, Expr as LeanExpr, ExprData, InductiveVal, Level, Name, NameData, RecursorRule, RecursorVal, }; -use crate::ix::ixon::CompileError; -use lean_ffi::nat::Nat; +use ixon::CompileError; use super::expr_utils::{ LocalDecl, decompose_apps, fresh_fvar, instantiate_spec_with_fvars, @@ -45,7 +43,7 @@ use super::expr_utils::{ /// /// The caller is responsible for applying `RestoreCtx::restore` to the /// output to replace auxiliary const references with original nested apps. -pub(crate) fn generate_recursors_from_expanded( +pub fn generate_recursors_from_expanded( sorted_classes: &[Vec], expanded: &super::nested::ExpandedBlock, // `source_of_canonical[canonical_i]` = Lean source-walk index `source_j` @@ -57,8 +55,8 @@ pub(crate) fn generate_recursors_from_expanded( // no nested-aux hash-sort permutation. source_of_canonical: Option<&[usize]>, lean_env: &LeanEnv, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result<(Vec<(Name, RecursorVal)>, bool), CompileError> { if expanded.types.is_empty() { return Ok((vec![], false)); @@ -292,11 +290,11 @@ struct FlatInfo { /// directly and pass the appropriate `KernelCtx` — this wrapper is kept /// only so unit tests don't have to plumb one through. #[cfg(test)] -pub(crate) fn generate_canonical_recursors( +pub fn generate_canonical_recursors( sorted_classes: &[Vec], lean_env: &LeanEnv, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result<(Vec<(Name, RecursorVal)>, bool), CompileError> { generate_canonical_recursors_with_overlay( sorted_classes, @@ -342,7 +340,7 @@ pub(crate) fn generate_canonical_recursors( fn reorder_flat_by_layout( flat: Vec, n_classes: usize, - layout: &crate::ix::ixon::env::AuxLayout, + layout: &ixon::env::AuxLayout, ) -> Result< Vec, (Vec, String), @@ -434,13 +432,13 @@ fn reorder_flat_by_layout( Ok(primary) } -pub(crate) fn generate_canonical_recursors_with_overlay( +pub fn generate_canonical_recursors_with_overlay( sorted_classes: &[Vec], lean_env: &LeanEnv, overlay: Option<&LeanEnv>, pre_flat: Option>, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result<(Vec<(Name, RecursorVal)>, bool), CompileError> { generate_canonical_recursors_with_layout( sorted_classes, @@ -455,20 +453,20 @@ pub(crate) fn generate_canonical_recursors_with_overlay( } /// Like [`generate_canonical_recursors_with_overlay`] but accepts an -/// optional [`crate::ix::ixon::env::AuxLayout`] that reorders the aux +/// optional [`ixon::env::AuxLayout`] that reorders the aux /// section of the flat block per its `perm` before recursor generation. /// /// This is the hook decompile uses to pin its canonical layout to /// compile's first-run result. With `aux_layout = None`, falls back to /// the discovery order produced by `build_compile_flat_block_with_overlay`. -pub(crate) fn generate_canonical_recursors_with_layout( +pub fn generate_canonical_recursors_with_layout( sorted_classes: &[Vec], lean_env: &LeanEnv, overlay: Option<&LeanEnv>, pre_flat: Option>, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, - aux_layout: Option<&crate::ix::ixon::env::AuxLayout>, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, + aux_layout: Option<&ixon::env::AuxLayout>, // Optional Lean-source index per canonical aux position, used for // emitting `all0.rec_{source_j + 1}` names directly. If provided // alongside `aux_layout`, both must agree (this parameter takes @@ -950,8 +948,8 @@ fn build_rec_type( rec_level_params: &[Name], lean_env: &LeanEnv, overlay: Option<&LeanEnv>, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, nested_rewrite: Option<&mut NestedRewriteCtx>, ) -> LeanExpr { let env_get = |name: &Name| -> Option { @@ -1350,8 +1348,8 @@ fn build_minor_type( motive_fvars: &[LeanExpr], ind_univs: &[Level], rec_level_params: &[Name], - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, // Shared scratch for nested-aux level rewrites across every ctor in // the block. `None` when the block doesn't need any rewriting. nested_rewrite: Option<&mut NestedRewriteCtx>, @@ -1631,8 +1629,8 @@ fn build_rec_rules( // Lean-source-indexed aux naming (see caller doc). `None` falls back // to `canonical_i + 1`. source_of_canonical: Option<&[usize]>, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, nested_rewrite: Option<&mut NestedRewriteCtx>, ) -> Result, CompileError> { let _ = n_classes; // Kept for signature parity with `build_rec_type`. @@ -2002,7 +2000,7 @@ fn build_rule_ih_fvar( /// Lean's `appendAfter`: append a suffix string to a Name. /// /// Matches `Init/Meta/Defs.lean:317-320`: -/// ``` +/// ```text /// def appendAfter (n : Name) (suffix : String) : Name := /// n.modifyBase fun /// | str p s => Name.mkStr p (s ++ suffix) @@ -2096,7 +2094,7 @@ fn find_rec_target( param_fvars: &[LeanExpr], n_params: usize, scope: &mut super::expr_utils::TcScope<'_>, - _stt: &crate::ix::compile::CompileState, + _stt: &crate::compile::CompileState, ) -> Option { // Phase 1: syntactic peel + match. let mut ty = dom.clone(); @@ -2330,15 +2328,15 @@ fn compute_is_large_and_k( n_classes: usize, n_params: usize, lean_env: &LeanEnv, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) -> Result<(bool, bool, bool), CompileError> { - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::ingress::{ + use ix_kernel::constant::KConst; + use ix_kernel::id::KId; + use ix_kernel::ingress::{ lean_expr_to_zexpr_with_kenv, resolve_lean_name_addr, }; - use crate::ix::kernel::mode::Meta; + use ix_kernel::mode::Meta; let n2a = Some(&stt.name_to_addr); let aux_n2a = Some(&stt.aux_name_to_addr); @@ -2351,7 +2349,7 @@ fn compute_is_large_and_k( u64, u64, Vec>, - crate::ix::kernel::expr::KExpr, + ix_kernel::expr::KExpr, bool, )> = Vec::new(); @@ -2459,7 +2457,7 @@ fn compute_is_large_and_k( let first_n_indices = ind_infos[0].2; // Use the TC for the appropriate context. - let mut tc = crate::ix::kernel::tc::TypeChecker::new(&mut kctx.kenv); + let mut tc = ix_kernel::tc::TypeChecker::new(&mut kctx.kenv); // Compute the WHNF-reduced result sort level via the kernel. This peels // params+indices with whnf at each step — crucial for inductives whose @@ -2533,7 +2531,7 @@ fn compute_is_large_and_k( && is_prop; let _cilk_elapsed = _cilk_start.elapsed(); - if *crate::ix::compile::IX_TIMING && _cilk_elapsed.as_secs_f32() > 0.1 { + if *crate::compile::IX_TIMING && _cilk_elapsed.as_secs_f32() > 0.1 { eprintln!( "[compute_is_large_and_k] {:?} total={:.3}s ingress={:.3}s n_classes={} kenv_size={}", classes[0].ind.cnst.name.pretty(), @@ -2553,8 +2551,8 @@ fn compute_is_large_and_k( fn ingress_target_type_deps( target_ty: &LeanExpr, lean_env: &LeanEnv, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) { let mut seen = rustc_hash::FxHashSet::default(); let mut queue = Vec::new(); @@ -2578,8 +2576,8 @@ fn ingress_field_deps( class: &FlatInfo, _lvl_params: &[Name], lean_env: &LeanEnv, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) { let mut seen = rustc_hash::FxHashSet::default(); let mut queue: Vec = Vec::new(); @@ -2603,8 +2601,8 @@ fn ingress_aux_gen_dep( name: &Name, ci: &ConstantInfo, lean_env: &LeanEnv, - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, queue: &mut Vec, ) { match ci { @@ -2653,15 +2651,15 @@ fn ingress_type_stub( name: &Name, typ: &LeanExpr, level_params: &[Name], - stt: &crate::ix::compile::CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + stt: &crate::compile::CompileState, + kctx: &mut crate::compile::KernelCtx, ) { - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::ingress::{ + use ix_kernel::constant::KConst; + use ix_kernel::id::KId; + use ix_kernel::ingress::{ lean_expr_to_zexpr_with_kenv, resolve_lean_name_addr, }; - use crate::ix::kernel::mode::Meta; + use ix_kernel::mode::Meta; let n2a = Some(&stt.name_to_addr); let aux_n2a = Some(&stt.aux_name_to_addr); @@ -2733,9 +2731,9 @@ fn collect_const_refs(expr: &LeanExpr, out: &mut Vec) { /// referenced by that same comment for the historical record. #[allow(dead_code)] fn peek_result_sort( - ty: &crate::ix::kernel::expr::KExpr, -) -> Option> { - use crate::ix::kernel::expr::ExprData as ZED; + ty: &ix_kernel::expr::KExpr, +) -> Option> { + use ix_kernel::expr::ExprData as ZED; let mut cur = ty.clone(); loop { match cur.data() { @@ -2749,7 +2747,7 @@ fn peek_result_sort( #[cfg(test)] mod tests { use super::*; - use crate::ix::compile::aux_gen::below::{ + use crate::compile::aux_gen::below::{ BelowConstant, generate_below_constants, }; @@ -2877,7 +2875,7 @@ mod tests { } fn insert_aux_stub_def(env: &mut LeanEnv, ind: &Name, suffix: &str) -> Name { - use crate::ix::env::{DefinitionSafety, DefinitionVal, ReducibilityHints}; + use ix_common::env::{DefinitionSafety, DefinitionVal, ReducibilityHints}; let def_name = Name::str(ind.clone(), suffix.into()); env.insert( @@ -3477,8 +3475,8 @@ mod tests { env.insert(ctor_name, ConstantInfo::CtorInfo(ctor)); let classes = vec![vec![ind_name]]; - let tmp_stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let tmp_stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); let (result, _is_prop) = generate_canonical_recursors(&classes, &env, &tmp_stt, &mut kctx) .unwrap(); @@ -3503,8 +3501,8 @@ mod tests { #[test] fn test_aux_gen_alpha_collapse() { let (env, a, b) = build_alpha_collapse_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); // After sort_consts collapse, A≅B → 1 class. let classes = vec![vec![a.clone(), b.clone()]]; @@ -3563,12 +3561,12 @@ mod tests { #[test] fn test_alpha_collapse_sort_consts_groups_inductives() { - use crate::ix::compile::{BlockCache, mk_indc, sort_consts}; - use crate::ix::env::ConstantInfo as LeanCI; - use crate::ix::mutual::MutConst; + use crate::compile::{BlockCache, mk_indc, sort_consts}; + use crate::mutual::MutConst; + use ix_common::env::ConstantInfo as LeanCI; let (env, a, b) = build_alpha_collapse_env(); - let stt = crate::ix::compile::CompileState::default(); + let stt = crate::compile::CompileState::default(); let mut cache = BlockCache::default(); let mut cs = Vec::new(); @@ -3594,7 +3592,7 @@ mod tests { #[test] fn test_alpha_collapse_compile_env_addresses_inductives_and_ctors() { - use crate::ix::compile::env::compile_env; + use crate::compile::env::compile_env; let (env, a, b) = build_alpha_collapse_env(); let lean_env = std::sync::Arc::new(env); @@ -3617,7 +3615,7 @@ mod tests { #[test] fn test_alpha_collapse_aux_gen_aliases_primary_aux_to_rep() { - use crate::ix::compile::aux_gen::{self, PatchedConstant}; + use crate::compile::aux_gen::{self, PatchedConstant}; let (mut env, a, b) = build_alpha_collapse_env(); let all = vec![a.clone(), b.clone()]; @@ -3633,8 +3631,8 @@ mod tests { let a_brecon = insert_aux_stub_def(&mut env, &a, "brecOn"); let b_brecon = insert_aux_stub_def(&mut env, &b, "brecOn"); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); let out = aux_gen::generate_aux_patches( &[vec![a.clone(), b.clone()]], &all, @@ -3675,8 +3673,8 @@ mod tests { #[test] fn test_aux_gen_alpha_collapse_3() { let (env, a, b, c) = build_alpha_collapse_3_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); // All 3 collapse into 1 class. let classes = vec![vec![a.clone(), b.clone(), c.clone()]]; @@ -3710,8 +3708,8 @@ mod tests { #[test] fn test_aux_gen_over_merge_alpha_collapse() { let (env, a, b, c) = build_over_merge_alpha_collapse_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); // A≅B collapse into 1 class, C is a separate class → 2 classes. let classes = vec![vec![a.clone(), b.clone()], vec![c.clone()]]; @@ -3767,8 +3765,8 @@ mod tests { #[test] fn test_aux_gen_over_merge() { let (env, a, b, c) = build_over_merge_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); // No alpha-collapse: A≠B (B has 2 fields), A≠C, B≠C → 3 classes. let classes = vec![vec![a.clone()], vec![b.clone()], vec![c.clone()]]; @@ -3810,8 +3808,8 @@ mod tests { #[test] fn test_aux_gen_below_indc_prop() { let (env, a, b) = build_alpha_collapse_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); let classes = vec![vec![a.clone(), b.clone()]]; let (recs, is_prop) = @@ -3846,8 +3844,8 @@ mod tests { #[test] fn test_aux_gen_below_def_type() { let (env, t) = build_type_nat_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); let classes = vec![vec![t.clone()]]; let (recs, is_prop) = @@ -3888,8 +3886,8 @@ mod tests { #[test] fn test_aux_gen_is_prop_vs_is_large() { let (env, p) = build_prop_drec_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); let classes = vec![vec![p.clone()]]; let (recs, is_prop) = @@ -3933,7 +3931,7 @@ mod tests { #[ignore] #[test] fn test_aux_gen_compile_roundtrip() { - use crate::ix::compile::env::compile_env; + use crate::compile::env::compile_env; use std::sync::Arc; let (mut env, a, b) = build_alpha_collapse_env(); @@ -3986,18 +3984,18 @@ mod tests { /// Type-level brecOn: Nat-like T generates .brecOn.go + .brecOn (no .eq without Eq in env). #[test] fn test_brecon_type_level() { - use crate::ix::compile::aux_gen::below::generate_below_constants; - use crate::ix::compile::aux_gen::brecon::generate_brecon_constants; + use crate::compile::aux_gen::below::generate_below_constants; + use crate::compile::aux_gen::brecon::generate_brecon_constants; let (env, t) = build_type_nat_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); // Ingress prelude (PUnit, PProd) and the inductive into the kenv // so TcScope can resolve them during brecOn sort-level inference. - crate::ix::compile::aux_gen::expr_utils::ensure_prelude_in_kenv_of( + crate::compile::aux_gen::expr_utils::ensure_prelude_in_kenv_of( &stt, &mut kctx, ); - crate::ix::compile::aux_gen::expr_utils::ensure_in_kenv_of( + crate::compile::aux_gen::expr_utils::ensure_in_kenv_of( &t, &env, &stt, &mut kctx, ); @@ -4012,7 +4010,7 @@ mod tests { assert_eq!(below.len(), 1); // Populate kenv with .below types for brecOn generation. - crate::ix::compile::aux_gen::populate_canon_kenv_with_below( + crate::compile::aux_gen::populate_canon_kenv_with_below( &below, &classes, &std::sync::Arc::new(env.clone()), @@ -4046,12 +4044,12 @@ mod tests { /// Prop-level brecOn: alpha-collapse A/B generates single .brecOn per class. #[test] fn test_brecon_prop_alpha_collapse() { - use crate::ix::compile::aux_gen::below::generate_below_constants; - use crate::ix::compile::aux_gen::brecon::generate_brecon_constants; + use crate::compile::aux_gen::below::generate_below_constants; + use crate::compile::aux_gen::brecon::generate_brecon_constants; let (env, a, b) = build_alpha_collapse_env(); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); let classes = vec![vec![a.clone(), b.clone()]]; let (recs, is_prop) = @@ -4081,8 +4079,8 @@ mod tests { /// Non-recursive inductives should NOT generate brecOn. #[test] fn test_brecon_skipped_for_non_recursive() { - use crate::ix::compile::aux_gen::below::generate_below_constants; - use crate::ix::compile::aux_gen::brecon::generate_brecon_constants; + use crate::compile::aux_gen::below::generate_below_constants; + use crate::compile::aux_gen::brecon::generate_brecon_constants; // Build a simple non-recursive inductive: Unit | unit : Unit let unit = n("Unit"); @@ -4122,8 +4120,8 @@ mod tests { }), ); - let stt = crate::ix::compile::CompileState::default(); - let mut kctx = crate::ix::compile::KernelCtx::new(); + let stt = crate::compile::CompileState::default(); + let mut kctx = crate::compile::KernelCtx::new(); let classes = vec![vec![unit]]; let (recs, is_prop) = generate_canonical_recursors(&classes, &env, &stt, &mut kctx).unwrap(); @@ -4150,7 +4148,7 @@ mod tests { /// with real Lean environments that include .below and .brecOn constants. #[test] fn test_brecon_type_compile_roundtrip() { - use crate::ix::compile::env::compile_env; + use crate::compile::env::compile_env; use std::sync::Arc; let (mut env, t) = build_type_nat_env(); diff --git a/src/ix/compile/env.rs b/crates/compile/src/compile/env.rs similarity index 98% rename from src/ix/compile/env.rs rename to crates/compile/src/compile/env.rs index 7f0731b8..0b36bc23 100644 --- a/src/ix/compile/env.rs +++ b/crates/compile/src/compile/env.rs @@ -14,15 +14,15 @@ use dashmap::DashMap; use rayon::prelude::*; use rustc_hash::FxHashSet; -use crate::ix::address::Address; -use crate::ix::compile::{ +use crate::compile::{ BlockCache, CompileOptions, CompileState, compile_const, compile_const_no_aux, }; -use crate::ix::condense::compute_sccs; -use crate::ix::env::{Env as LeanEnv, Name}; -use crate::ix::graph::{NameSet, build_ref_graph}; -use crate::ix::ground::ground_consts; -use crate::ix::ixon::CompileError; +use crate::condense::compute_sccs; +use crate::graph::{NameSet, build_ref_graph}; +use crate::ground::ground_consts; +use ix_common::address::Address; +use ix_common::env::{Env as LeanEnv, Name}; +use ixon::CompileError; // =========================================================================== // Progress + diagnostic logging @@ -150,8 +150,7 @@ pub fn compile_env_with_options( // Filter ungrounded names from the ref graph before SCC computation so // condensed blocks only contain constants we can actually compile. - let grounded_out_refs: crate::ix::graph::RefMap = if ungrounded_map.is_empty() - { + let grounded_out_refs: crate::graph::RefMap = if ungrounded_map.is_empty() { graph.out_refs } else { graph @@ -455,7 +454,7 @@ pub fn compile_env_with_options( // Spawn worker threads for _ in 0..num_threads { s.spawn(move || { - let mut worker_kctx = crate::ix::compile::KernelCtx::new(); + let mut worker_kctx = crate::compile::KernelCtx::new(); loop { // Try to get work from the ready queue let work = { @@ -742,7 +741,7 @@ pub fn compile_env_with_options( // Check for slow blocks let elapsed = block_start.elapsed(); - if *crate::ix::compile::IX_TIMING && elapsed.as_secs_f32() > 1.0 { + if *crate::compile::IX_TIMING && elapsed.as_secs_f32() > 1.0 { let cc_time = _cc_start.elapsed().as_secs_f32(); eprintln!( "Slow block {:?} ({} consts): {:.2}s path={} cc={:.2}s", @@ -956,7 +955,7 @@ fn aux_gen_seed_names() -> Vec { /// references; we resolve each referenced name back to its own SCC-rep via /// `condensed.low_links`. fn precompile_aux_gen_prereqs( - condensed: &crate::ix::condense::CondensedBlocks, + condensed: &crate::condense::CondensedBlocks, lean_env: &Arc, stt: &CompileState, ) -> Result<(), CompileError> { @@ -1011,7 +1010,7 @@ fn precompile_aux_gen_prereqs( // Compile each SCC in dep-first order, moving compiled names to // `aux_name_to_addr` so later SCCs can resolve their Const refs. - let mut prereq_kctx = crate::ix::compile::KernelCtx::new(); + let mut prereq_kctx = crate::compile::KernelCtx::new(); for rep in order { if stt.aux_name_to_addr.contains_key(&rep) { continue; // Already compiled (e.g., via a prior prereq run). diff --git a/src/ix/compile/mutual.rs b/crates/compile/src/compile/mutual.rs similarity index 97% rename from src/ix/compile/mutual.rs rename to crates/compile/src/compile/mutual.rs index fa7ef7d9..68bbca19 100644 --- a/src/ix/compile/mutual.rs +++ b/crates/compile/src/compile/mutual.rs @@ -15,23 +15,24 @@ use std::sync::Arc; use rustc_hash::FxHashMap; -use lean_ffi::nat::Nat; - -use crate::ix::address::Address; -use crate::ix::compile::aux_gen::below::BelowIndc; -use crate::ix::compile::aux_gen::brecon::BRecOnDef; -use crate::ix::compile::aux_gen::recursor; -use crate::ix::compile::aux_gen::{self, PatchedConstant}; -use crate::ix::compile::{ +use bignat::Nat; + +use crate::compile::aux_gen::below::BelowIndc; +use crate::compile::aux_gen::brecon::BRecOnDef; +use crate::compile::aux_gen::recursor; +use crate::compile::aux_gen::{self, PatchedConstant}; +use crate::compile::{ BlockCache, CompileState, collect_mut_const_exprs, compile_definition, compile_inductive, compile_mutual_block, compile_name, compile_recursor, preseed_expr_tables, sort_consts, }; -use crate::ix::env::{ +use crate::mutual::{Def, Ind, MutConst}; +use ix_common::address::Address; +use ix_common::env::{ ConstantInfo as LeanConstantInfo, ConstantVal, ConstructorVal, DefinitionSafety, Env as LeanEnv, Name, ReducibilityHints, }; -use crate::ix::ixon::{ +use ixon::{ CompileError, constant::{ Constant, DefKind, MutConst as IxonMutConst, ctor_proj_constant, @@ -41,7 +42,6 @@ use crate::ix::ixon::{ metadata::{ConstantMeta, ConstantMetaInfo}, univ::Univ, }; -use crate::ix::mutual::{Def, Ind, MutConst}; // =========================================================================== // compile_aux_block @@ -57,11 +57,11 @@ use crate::ix::mutual::{Def, Ind, MutConst}; /// `stt.name_to_addr`) so they don't interfere with the scheduler's /// dependency tracking. The scheduler's promotion path in `env.rs` moves /// them to `name_to_addr` when the block is processed. -pub(crate) fn compile_aux_block( +pub fn compile_aux_block( aux_consts: &[MutConst], lean_env: &Arc, stt: &CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + kctx: &mut crate::compile::KernelCtx, ) -> Result<(), CompileError> { compile_aux_block_with_rename(aux_consts, lean_env, stt, kctx, None, None) } @@ -95,16 +95,16 @@ pub(crate) fn compile_aux_block( /// Without this reorder, `sort_consts` on recursors picks an independent /// canonical permutation that diverges from the inductive block's layout. /// See `docs/ix_canonicity.md` §6.2 and the rationale in -/// `kernel::inductive::populate_recursor_rules_from_block`. +/// `ix_kernel::inductive::populate_recursor_rules_from_block`. /// /// The class ordering produced by `sort_consts` is preserved as a /// stable tiebreak: classes that map to `u64::MAX` (no key entry) keep /// their `sort_consts` relative position at the tail. -pub(crate) fn compile_aux_block_with_rename( +pub fn compile_aux_block_with_rename( aux_consts: &[MutConst], lean_env: &Arc, stt: &CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + kctx: &mut crate::compile::KernelCtx, name_rename: Option<&FxHashMap>, class_order_key: Option<&dyn Fn(&MutConst) -> u64>, ) -> Result<(), CompileError> { @@ -199,7 +199,7 @@ pub(crate) fn compile_aux_block_with_rename( if ixon_mutuals.len() == 1 && !matches!(&ixon_mutuals[0], IxonMutConst::Indc(_)) { - use crate::ix::compile::{ + use crate::compile::{ apply_sharing_to_definition_with_stats, apply_sharing_to_recursor_with_stats, }; @@ -508,13 +508,13 @@ fn content_address(constant: &Constant) -> Address { /// /// Only runs for inductive blocks. Non-inductive mutual blocks return /// immediately. -pub(crate) fn generate_and_compile_aux_recursors( +pub fn generate_and_compile_aux_recursors( cs: &[MutConst], class_names: &[Vec], lean_env: &Arc, stt: &CompileState, - kctx: &mut crate::ix::compile::KernelCtx, -) -> Result, CompileError> { + kctx: &mut crate::compile::KernelCtx, +) -> Result, CompileError> { // Guard: aux_gen canonical generation only runs for blocks containing // inductives. Non-inductive blocks (plain defs, recursor-only SCCs, // etc.) have no canonical auxiliaries to generate. @@ -603,7 +603,7 @@ pub(crate) fn generate_and_compile_aux_recursors( // `original_all` (= `source_all` above) is hoisted to the enclosing // scope so the aux-name rename map construction below can reuse it. let original_all: Vec = source_all; - let mut aux_layout: Option = None; + let mut aux_layout: Option = None; if !original_all.is_empty() && let Some(perm) = aux_out.perm.clone() && !perm.is_empty() @@ -639,7 +639,7 @@ pub(crate) fn generate_and_compile_aux_recursors( }); } aux_layout = - Some(crate::ix::compile::surgery::AuxLayout { perm, source_ctor_counts }); + Some(crate::compile::surgery::AuxLayout { perm, source_ctor_counts }); } // NOTE: Historically, a canonical→source rename map was built here @@ -889,7 +889,7 @@ pub(crate) fn generate_and_compile_aux_recursors( // blocks). See the aux_gen.rs module docs for the full rationale. let total = aux_total_start.elapsed(); - if *crate::ix::compile::IX_TIMING && total.as_secs_f32() > 0.5 { + if *crate::compile::IX_TIMING && total.as_secs_f32() > 0.5 { eprintln!( "[aux_gen] {:?} total={:.2}s gen={:.2}s rec={:.2}s cases={:.2}s recOn={:.2}s below={:.2}s belowRec={:.2}s brecon={:.2}s patches={}", block_label, @@ -939,7 +939,7 @@ fn below_indc_to_mut_const( .collect(); MutConst::Indc(Ind { - ind: crate::ix::env::InductiveVal { + ind: ix_common::env::InductiveVal { cnst: ConstantVal { name: bi.name.clone(), level_params: bi.level_params.clone(), @@ -1054,7 +1054,7 @@ fn compile_below_recursors( below_indcs: &[MutConst], lean_env: &Arc, stt: &CompileState, - kctx: &mut crate::ix::compile::KernelCtx, + kctx: &mut crate::compile::KernelCtx, ) -> Result<(), CompileError> { // Build a small overlay with just the .below inductives + ctors. // These don't exist in the original lean_env, but generate_canonical_recursors diff --git a/src/ix/compile/nat_conv.rs b/crates/compile/src/compile/nat_conv.rs similarity index 82% rename from src/ix/compile/nat_conv.rs rename to crates/compile/src/compile/nat_conv.rs index b1a2be22..a96ec090 100644 --- a/src/ix/compile/nat_conv.rs +++ b/crates/compile/src/compile/nat_conv.rs @@ -5,14 +5,14 @@ //! `num_nested`) are always small values. These utilities make the conversion //! explicit rather than silently producing 0 on overflow. -use lean_ffi::nat::Nat; +use bignat::Nat; -use crate::ix::ixon::CompileError; +use ixon::CompileError; /// Convert a Lean `Nat` to `usize`, returning `CompileError` on overflow. /// /// Use in functions that return `Result<_, CompileError>`. -pub(crate) fn try_nat_to_usize(n: &Nat) -> Result { +pub fn try_nat_to_usize(n: &Nat) -> Result { n.to_u64().map(|v| v as usize).ok_or_else(|| CompileError::UnsupportedExpr { desc: "Nat field exceeds u64".into(), }) @@ -23,11 +23,11 @@ pub(crate) fn try_nat_to_usize(n: &Nat) -> Result { /// Use in pure functions where returning `Result` would cascade through /// callers. Overflow is impossible for valid Lean metadata — these fields /// represent type constructor arities which are always < 2^64. -pub(crate) fn nat_to_usize(n: &Nat) -> usize { +pub fn nat_to_usize(n: &Nat) -> usize { n.to_u64().expect("Nat field exceeds u64") as usize } /// Convert a Lean `Nat` to `u64`, panicking on overflow. -pub(crate) fn nat_to_u64(n: &Nat) -> u64 { +pub fn nat_to_u64(n: &Nat) -> u64 { n.to_u64().expect("Nat field exceeds u64") } diff --git a/src/ix/compile/surgery.rs b/crates/compile/src/compile/surgery.rs similarity index 98% rename from src/ix/compile/surgery.rs rename to crates/compile/src/compile/surgery.rs index fb204f14..94a5029d 100644 --- a/src/ix/compile/surgery.rs +++ b/crates/compile/src/compile/surgery.rs @@ -23,12 +23,12 @@ use std::sync::Arc; use rustc_hash::FxHashMap; -use crate::ix::env::{ +use ix_common::env::{ ConstantInfo as LeanConstantInfo, ConstructorVal, Env as LeanEnv, Expr as LeanExpr, ExprData, Level, Name, NameData, RecursorVal, }; -use crate::ix::ixon::error::CompileError; -use crate::ix::ixon::expr::Expr as IxonExpr; +use ixon::error::CompileError; +use ixon::expr::Expr as IxonExpr; use super::{ aux_gen::expr_utils::{ @@ -151,7 +151,7 @@ impl BRecOnCallSitePlan { } } -pub(crate) fn rec_name_to_brecon_name(name: &Name) -> Option { +pub fn rec_name_to_brecon_name(name: &Name) -> Option { match name.as_data() { NameData::Str(parent, s, _) if s == "rec" => { Some(Name::str(parent.clone(), "brecOn".to_string())) @@ -163,7 +163,7 @@ pub(crate) fn rec_name_to_brecon_name(name: &Name) -> Option { } } -pub(crate) fn rec_name_to_below_name(name: &Name) -> Option { +pub fn rec_name_to_below_name(name: &Name) -> Option { match name.as_data() { NameData::Str(parent, s, _) if s == "rec" => { Some(Name::str(parent.clone(), "below".to_string())) @@ -182,7 +182,7 @@ pub(crate) fn rec_name_to_below_name(name: &Name) -> Option { /// Collect a Lean App telescope: peel App nodes to get `(head, [a1, ..., aN])`. /// /// Arguments are returned in application order (leftmost first). -pub(crate) fn collect_lean_telescope<'a>( +pub fn collect_lean_telescope<'a>( e: &'a LeanExpr, ) -> (&'a LeanExpr, Vec<&'a LeanExpr>) { let mut args: Vec<&'a LeanExpr> = Vec::new(); @@ -199,7 +199,7 @@ pub(crate) fn collect_lean_telescope<'a>( /// /// Arguments are returned in application order (leftmost first). #[allow(dead_code)] -pub(crate) fn collect_ixon_telescope( +pub fn collect_ixon_telescope( e: &Arc, ) -> (Arc, Vec>) { let mut args: Vec> = Vec::new(); @@ -237,14 +237,14 @@ pub(crate) fn collect_ixon_telescope( /// its own plan). We skip generating a plan for a phantom `X.rec` /// itself, since that belongs to the block owning `X`. /// -/// The [`AuxLayout`] type is re-exported from `crate::ix::ixon::env` so it +/// The [`AuxLayout`] type is re-exported from `ixon::env` so it /// can live in the Ixon env side-table and survive serialization — see the -/// doc on [`crate::ix::ixon::env::AuxLayout`] for the canonical definition. -pub(crate) use crate::ix::ixon::env::AuxLayout; +/// doc on [`ixon::env::AuxLayout`] for the canonical definition. +pub use ixon::env::AuxLayout; const PERM_OUT_OF_SCC: usize = usize::MAX; -pub(crate) fn compute_call_site_plans( +pub fn compute_call_site_plans( sorted_classes: &[Vec], original_all: &[Name], lean_env: &LeanEnv, @@ -706,7 +706,7 @@ pub(crate) fn compute_call_site_plans( /// recursor call then goes through the normal call-site surgery for its own /// SCC. #[allow(clippy::too_many_arguments)] -pub(crate) fn adapt_split_minor( +pub fn adapt_split_minor( rec_name: &Name, rec_levels: &[Level], plan: &CallSitePlan, @@ -1115,8 +1115,8 @@ fn dump_plan_state( #[cfg(test)] mod tests { use super::*; - use crate::ix::env::{ConstantVal, ConstructorVal, InductiveVal}; - use lean_ffi::nat::Nat; + use bignat::Nat; + use ix_common::env::{ConstantVal, ConstructorVal, InductiveVal}; fn n(s: &str) -> Name { Name::str(Name::anon(), s.to_string()) @@ -1208,8 +1208,8 @@ mod tests { fn build_test_env( names: &[&str], ctor_counts: &[usize], - ) -> crate::ix::env::Env { - let mut env = crate::ix::env::Env::default(); + ) -> ix_common::env::Env { + let mut env = ix_common::env::Env::default(); let all: Vec = names.iter().map(|s| n(s)).collect(); for (i, &name_str) in names.iter().enumerate() { @@ -1398,7 +1398,7 @@ mod tests { ctor_counts: &[usize], aux_motives: usize, aux_minors: usize, - ) -> crate::ix::env::Env { + ) -> ix_common::env::Env { let mut env = build_test_env(names, ctor_counts); // Overwrite each inductive's recursor with inflated motive/minor counts. let total_motives = (names.len() + aux_motives) as u64; diff --git a/src/ix/condense.rs b/crates/compile/src/condense.rs similarity index 98% rename from src/ix/condense.rs rename to crates/compile/src/condense.rs index ab0a6b27..f293aaa0 100644 --- a/src/ix/condense.rs +++ b/crates/compile/src/condense.rs @@ -5,11 +5,10 @@ use rustc_hash::FxHashMap; -use crate::{ - FxIndexSet, - ix::env::Name, - ix::graph::{NameSet, RefMap}, -}; +use ix_common::FxIndexSet; +use ix_common::env::Name; + +use crate::graph::{NameSet, RefMap}; /// The condensation of a reference graph into strongly connected components. pub struct CondensedBlocks { diff --git a/src/ix/congruence.rs b/crates/compile/src/congruence.rs similarity index 98% rename from src/ix/congruence.rs rename to crates/compile/src/congruence.rs index 4f075020..c74c2ee3 100644 --- a/src/ix/congruence.rs +++ b/crates/compile/src/congruence.rs @@ -14,8 +14,8 @@ pub mod perm; -use crate::ix::env::{ConstantInfo, Expr, ExprData, Level, LevelData, Literal}; -use lean_ffi::nat::Nat; +use bignat::Nat; +use ix_common::env::{ConstantInfo, Expr, ExprData, Level, LevelData, Literal}; /// Check that two Lean levels are equal modulo the same simplifications /// `Level::max_smart` / `Level::imax_smart` perform. @@ -334,7 +334,7 @@ pub fn const_alpha_eq( // ========================================================================= /// Strip Mdata wrappers from an expression. -pub(crate) fn strip_mdata(e: &Expr) -> &Expr { +pub fn strip_mdata(e: &Expr) -> &Expr { let mut cur = e; while let ExprData::Mdata(_, inner, _) = cur.as_data() { cur = inner; @@ -342,11 +342,7 @@ pub(crate) fn strip_mdata(e: &Expr) -> &Expr { cur } -pub(crate) fn check_nat_eq( - a: &Nat, - b: &Nat, - field: &str, -) -> Result<(), String> { +pub fn check_nat_eq(a: &Nat, b: &Nat, field: &str) -> Result<(), String> { let av = a.to_u64().unwrap_or(u64::MAX); let bv = b.to_u64().unwrap_or(u64::MAX); if av != bv { @@ -411,7 +407,7 @@ mod tests { //! `Level::imax_smart` (see `src/ix/env.rs:340-404`), so they double //! as a contract test for those constructors. use super::*; - use crate::ix::env::Name; + use ix_common::env::Name; fn p(s: &str) -> Level { Level::param(Name::str(Name::anon(), s.to_string())) } diff --git a/src/ix/congruence/perm.rs b/crates/compile/src/congruence/perm.rs similarity index 99% rename from src/ix/congruence/perm.rs rename to crates/compile/src/congruence/perm.rs index 3def435b..f179c39e 100644 --- a/src/ix/congruence/perm.rs +++ b/crates/compile/src/congruence/perm.rs @@ -65,19 +65,16 @@ //! - `InductInfo`, `CtorInfo`, `AxiomInfo`, `QuotInfo` — pass-through //! (no permutation needed). -use lean_ffi::nat::Nat; +use bignat::Nat; use rustc_hash::FxHashMap; -use crate::ix::compile::aux_gen::expr_utils::{ - forall_telescope, lambda_telescope, -}; -use crate::ix::{ - address::Address, - env::{ - ConstantInfo, ConstantVal, Expr, ExprData, Name, RecursorRule, RecursorVal, - }, +use ix_common::address::Address; +use ix_common::env::{ + ConstantInfo, ConstantVal, Expr, ExprData, Name, RecursorRule, RecursorVal, }; +use crate::compile::aux_gen::expr_utils::{forall_telescope, lambda_telescope}; + use super::{check_nat_eq, expr_alpha_eq, level_alpha_eq, strip_mdata}; /// Sentinel for `aux_perm` entries that don't correspond to any canonical @@ -352,7 +349,7 @@ impl PermCtx { /// counterparts. Built once per binder telescope, passed by shared /// reference into the alpha-eq walk. #[derive(Default, Clone)] -pub(crate) struct Corr { +pub struct Corr { fvar_map: FxHashMap, fvar_alts: FxHashMap>, punit_motive_gen: Vec, @@ -538,7 +535,7 @@ fn classify_defn_shape(name: &Name) -> DefnShape { /// Collect up to `n` trailing `Str` segments of `name`, from leaf /// outward. `Num` segments or `Anonymous` terminate collection early. fn collect_name_tail_strs(name: &Name, n: usize) -> Vec { - use crate::ix::env::NameData; + use ix_common::env::NameData; let mut out: Vec = Vec::with_capacity(n); let mut cur = name.clone(); for _ in 0..n { @@ -1273,8 +1270,8 @@ fn n_canonical_minors_of(ctx: &PermCtx) -> usize { fn add_motive_alts( corr: &mut Corr, ctx: &PermCtx, - orig_decls: &[crate::ix::compile::aux_gen::expr_utils::LocalDecl], - gen_decls: &[crate::ix::compile::aux_gen::expr_utils::LocalDecl], + orig_decls: &[crate::compile::aux_gen::expr_utils::LocalDecl], + gen_decls: &[crate::compile::aux_gen::expr_utils::LocalDecl], ) { let n_params = ctx.n_params; let n_source_motives = ctx.n_source_motives(); @@ -1353,7 +1350,7 @@ fn is_motive_app(e: &Expr, motives: &[Name]) -> bool { /// - `LetE` / `Proj` / `Mdata`: recurse; `Mdata` is stripped before /// matching so it's essentially a no-op. /// - `Sort`, `Lit`: compare literally. -pub(crate) fn expr_alpha_eq_ctx( +pub fn expr_alpha_eq_ctx( g: &Expr, orig: &Expr, ctx: &PermCtx, @@ -1800,9 +1797,8 @@ fn peel_all_lambdas( expr: &Expr, prefix: &str, min_count: usize, -) -> (Vec, Vec, Expr) -{ - use crate::ix::compile::aux_gen::expr_utils::LocalDecl; +) -> (Vec, Vec, Expr) { + use crate::compile::aux_gen::expr_utils::LocalDecl; let (mut fvars, mut decls, mut body): (Vec, Vec, Expr) = if min_count == 0 { diff --git a/src/ix/decompile.rs b/crates/compile/src/decompile.rs similarity index 98% rename from src/ix/decompile.rs rename to crates/compile/src/decompile.rs index 3a954a7b..6f5edcc3 100644 --- a/src/ix/decompile.rs +++ b/crates/compile/src/decompile.rs @@ -9,35 +9,37 @@ #![allow(clippy::map_err_ignore)] #![allow(clippy::match_same_arms)] -use lean_ffi::nat::Nat; +use bignat::Nat; + +use ix_common::address::Address; +use ix_common::env::{ + AxiomVal, BinderInfo, ConstantInfo as LeanConstantInfo, ConstantVal, + ConstructorVal, DataValue as LeanDataValue, DefinitionSafety, DefinitionVal, + Env as LeanEnv, Expr as LeanExpr, InductiveVal, Int, Level, Literal, Name, + OpaqueVal, QuotVal, RecursorRule as LeanRecursorRule, RecursorVal, + ReducibilityHints, SourceInfo, Substring, Syntax, SyntaxPreresolved, + TheoremVal, +}; -use crate::{ - ix::address::Address, - ix::compile::CompileState, - ix::env::{ - AxiomVal, BinderInfo, ConstantInfo as LeanConstantInfo, ConstantVal, - ConstructorVal, DataValue as LeanDataValue, DefinitionSafety, - DefinitionVal, Env as LeanEnv, Expr as LeanExpr, InductiveVal, Int, Level, - Literal, Name, OpaqueVal, QuotVal, RecursorRule as LeanRecursorRule, - RecursorVal, ReducibilityHints, SourceInfo, Substring, Syntax, - SyntaxPreresolved, TheoremVal, +use ixon::{ + DecompileError, Tag0, + constant::{ + Axiom, Constant, ConstantInfo, Constructor, DefKind, Definition, + DefinitionProj, Inductive, InductiveProj, MutConst, Quotient, Recursor, + RecursorProj, }, - ix::ixon::{ - DecompileError, Tag0, - constant::{ - Axiom, Constant, ConstantInfo, Constructor, DefKind, Definition, - DefinitionProj, Inductive, InductiveProj, MutConst, Quotient, Recursor, - RecursorProj, - }, - env::Named, - expr::Expr, - metadata::{ - CallSiteEntry, ConstantMeta, ConstantMetaInfo, DataValue, ExprMeta, - ExprMetaData, KVMap, - }, - univ::Univ, + env::Named, + expr::Expr, + metadata::{ + CallSiteEntry, ConstantMeta, ConstantMetaInfo, DataValue, ExprMeta, + ExprMetaData, KVMap, }, - ix::mutual::{Def, Ind, MutConst as LeanMutConst, MutCtx, all_to_ctx}, + univ::Univ, +}; + +use crate::{ + compile::CompileState, + mutual::{Def, Ind, MutConst as LeanMutConst, MutCtx, all_to_ctx}, }; use dashmap::DashMap; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; @@ -1913,14 +1915,14 @@ enum AuxKind { /// we're going to regenerate anyway should never have its call-sites /// surgered, since the regenerated body is emitted in canonical order /// by construction. -pub(crate) fn is_aux_gen_suffix(name: &Name) -> bool { +pub fn is_aux_gen_suffix(name: &Name) -> bool { classify_aux_gen(name).is_some() } /// Classify an aux_gen constant by suffix, returning (kind, root_inductive). /// The root inductive is the base inductive the auxiliary is derived from. fn classify_aux_gen(name: &Name) -> Option<(AuxKind, Name)> { - use crate::ix::env::NameData; + use ix_common::env::NameData; let s1 = name.last_str()?; let p1 = match name.as_data() { NameData::Str(parent, _, _) => parent.clone(), @@ -2015,7 +2017,7 @@ fn def_safety(is_unsafe: bool) -> DefinitionSafety { /// `mkDefinitionValInferringUnsafe`, which always flips to `Unsafe` when the /// parent inductive is unsafe (the value references the parent's `.rec`). fn below_def_to_lean( - def: &crate::ix::compile::aux_gen::below::BelowDef, + def: &crate::compile::aux_gen::below::BelowDef, ) -> LeanConstantInfo { LeanConstantInfo::DefnInfo(DefinitionVal { cnst: ConstantVal { @@ -2036,7 +2038,7 @@ fn below_def_to_lean( /// branch of `IndPredBelow`). The constructor `is_unsafe` matches the /// enclosing inductive — the kernel rejects mixed safety within an inductive. fn below_indc_to_lean( - indc: &crate::ix::compile::aux_gen::below::BelowIndc, + indc: &crate::compile::aux_gen::below::BelowIndc, all_below_names: &[Name], ) -> (InductiveVal, Vec) { let ctor_names: Vec = @@ -2096,7 +2098,7 @@ fn below_indc_to_lean( /// (`Lean/Environment.lean:2797`), which replaces a theorem with an unsafe /// definition whenever `env.hasUnsafe` fires on the type or value. fn brecon_def_to_lean( - def: &crate::ix::compile::aux_gen::brecon::BRecOnDef, + def: &crate::compile::aux_gen::brecon::BRecOnDef, ) -> LeanConstantInfo { let cnst = ConstantVal { name: def.name.clone(), @@ -2408,11 +2410,11 @@ fn roundtrip_block( stt: &CompileState, dstt: &DecompileState, ) -> Result, DecompileError> { - use crate::ix::compile::{ + use crate::compile::{ BlockCache as CompileBlockCache, compile_definition, compile_inductive, compile_mutual_block, compile_recursor, sort_consts, }; - use crate::ix::mutual::ctx_to_all; + use crate::mutual::ctx_to_all; let mut results: FxHashMap = FxHashMap::default(); if consts.is_empty() { @@ -2507,7 +2509,7 @@ fn roundtrip_block( // Singleton: compile as bare constant (no Muts wrapper). let result = match &ixon_mutuals[0] { MutConst::Defn(def) => { - crate::ix::compile::apply_sharing_to_definition_with_stats( + crate::compile::apply_sharing_to_definition_with_stats( def.clone(), block_refs, block_univs, @@ -2515,7 +2517,7 @@ fn roundtrip_block( ) }, MutConst::Recr(rec) => { - crate::ix::compile::apply_sharing_to_recursor_with_stats( + crate::compile::apply_sharing_to_recursor_with_stats( rec.clone(), block_refs, block_univs, @@ -3182,7 +3184,7 @@ fn decompile_named_const( /// Idempotent: if `stt.aux_perms` already has an entry for the name, we /// leave it alone (compile-in-progress stt wins over rehydrated copy). fn rehydrate_aux_perms_from_env(stt: &CompileState) { - use crate::ix::ixon::metadata::ConstantMetaInfo; + use ixon::metadata::ConstantMetaInfo; let mut n_muts = 0usize; let mut n_muts_with_layout = 0usize; @@ -3294,7 +3296,7 @@ fn block_mut_consts_from_env( #[derive(Clone)] struct StoredPlanBlock { class_names: Vec>, - aux_layout: Option, + aux_layout: Option, flat_names: Vec, } @@ -3390,7 +3392,7 @@ fn fallback_plan_blocks_from_sort( env: &LeanEnv, stt: &CompileState, ) -> Result, DecompileError> { - use crate::ix::compile::{BlockCache as CompileBlockCache, sort_consts}; + use crate::compile::{BlockCache as CompileBlockCache, sort_consts}; let cs = block_mut_consts_from_env(all_names, env)?; if cs.is_empty() { @@ -3422,7 +3424,7 @@ fn install_decompile_call_site_plans( env: &LeanEnv, stt: &CompileState, ) -> Result<(), DecompileError> { - use crate::ix::compile::{aux_gen, surgery}; + use crate::compile::{aux_gen, surgery}; if all_names.is_empty() { return Ok(()); @@ -3502,11 +3504,11 @@ fn decompile_block_aux_gen( all_names: &[Name], aux_members: &[(AuxKind, Name)], env: &mut LeanEnv, - kctx: &mut crate::ix::compile::KernelCtx, + kctx: &mut crate::compile::KernelCtx, stt: &CompileState, dstt: &DecompileState, ) -> Vec<(Name, DecompileError)> { - use crate::ix::compile::aux_gen::{ + use crate::compile::aux_gen::{ below::{BelowConstant, generate_below_constants}, brecon::generate_brecon_constants, cases_on::generate_cases_on, @@ -3541,7 +3543,7 @@ fn decompile_block_aux_gen( // Ingress transitive dependencies from constructor field types. { - use crate::ix::graph::get_constant_info_references; + use crate::graph::get_constant_info_references; for ind_name in all_names { if let Some(ci) = env.get(ind_name) { for ref_name in get_constant_info_references(ci) { @@ -3587,7 +3589,7 @@ fn decompile_block_aux_gen( // // See `docs/ix_canonicity.md` §9.3 / §17.2 for the canonicity // commitment this upholds. - let aux_layout_for_block: Option = None; + let aux_layout_for_block: Option = None; let (canonical_recs, is_prop) = if needs_rec || needs_rec_on @@ -3596,7 +3598,7 @@ fn decompile_block_aux_gen( || needs_below_rec || needs_brecon { - match crate::ix::compile::aux_gen::recursor::generate_canonical_recursors_with_layout( + match crate::compile::aux_gen::recursor::generate_canonical_recursors_with_layout( &classes, env, None, None, stt, kctx, aux_layout_for_block.as_ref(), None, // source_of_canonical derived from aux_layout inside _with_layout @@ -3697,7 +3699,7 @@ fn decompile_block_aux_gen( for co_name in &cases_on_members { let ind_name = match co_name.as_data() { - crate::ix::env::NameData::Str(parent, _, _) => parent.clone(), + ix_common::env::NameData::Str(parent, _, _) => parent.clone(), _ => continue, }; let rec_name = Name::str(ind_name.clone(), "rec".to_string()); @@ -3768,7 +3770,7 @@ fn decompile_block_aux_gen( // Phase 1c: Generate .recOn definitions (arg-reordered .rec wrapper). if needs_rec_on { - use crate::ix::compile::aux_gen::rec_on::generate_rec_on; + use crate::compile::aux_gen::rec_on::generate_rec_on; let rec_on_members: Vec<&Name> = aux_members .iter() @@ -3778,7 +3780,7 @@ fn decompile_block_aux_gen( for ro_name in &rec_on_members { let ind_name = match ro_name.as_data() { - crate::ix::env::NameData::Str(parent, _, _) => parent.clone(), + ix_common::env::NameData::Str(parent, _, _) => parent.clone(), _ => continue, }; let rec_name = Name::str(ind_name, "rec".to_string()); @@ -4233,8 +4235,7 @@ fn decompile_block_aux_gen( if let Some(orig) = orig_env { for (name, generated_ci) in &generated_consts { if let Some(orig_ci) = orig.get(name) - && let Err(e) = - crate::ix::congruence::const_alpha_eq(generated_ci, orig_ci) + && let Err(e) = crate::congruence::const_alpha_eq(generated_ci, orig_ci) { aux_gen_errors.push(( name.clone(), @@ -4262,10 +4263,10 @@ fn decompile_block_aux_gen( pub fn decompile_env( stt: &CompileState, ) -> Result { - use crate::ix::compile::KernelCtx; - use crate::ix::compile::aux_gen::expr_utils; - use crate::ix::condense::compute_sccs; - use crate::ix::graph::{NameSet, RefMap, get_constant_info_references}; + use crate::compile::KernelCtx; + use crate::compile::aux_gen::expr_utils; + use crate::condense::compute_sccs; + use crate::graph::{NameSet, RefMap, get_constant_info_references}; let dstt = DecompileState::default(); @@ -4660,8 +4661,8 @@ pub fn check_decompile( #[cfg(test)] mod tests { use super::*; - use crate::ix::compile::compile_name; - use crate::ix::env::Level; + use crate::compile::compile_name; + use ix_common::env::Level; /// Register a Name in `stt.env.names` so `decompile_name` can resolve it. /// Mirrors `compile_name` (content-address the name, insert into names map). @@ -4674,7 +4675,7 @@ mod tests { fn lean_telescope(e: &LeanExpr) -> (LeanExpr, Vec) { let mut args = Vec::new(); let mut cur = e.clone(); - while let crate::ix::env::ExprData::App(f, a, _) = cur.as_data() { + while let ix_common::env::ExprData::App(f, a, _) = cur.as_data() { args.push(a.clone()); cur = f.clone(); } @@ -4685,7 +4686,7 @@ mod tests { /// Pull the bvar index out of a Lean expr, or None if it isn't a bvar. fn bvar_idx(e: &LeanExpr) -> Option { match e.as_data() { - crate::ix::env::ExprData::Bvar(n, _) => n.to_u64(), + ix_common::env::ExprData::Bvar(n, _) => n.to_u64(), _ => None, } } @@ -4773,7 +4774,7 @@ mod tests { // The reconstructed spine should be in *source* order: Var 10, 11, 12. let (head_lean, args) = lean_telescope(&decompiled); match head_lean.as_data() { - crate::ix::env::ExprData::Const(name, _, _) => { + ix_common::env::ExprData::Const(name, _, _) => { assert_eq!(*name, head_name, "head const name mismatch"); }, other => panic!("expected Const head, got {other:?}"), @@ -4872,7 +4873,7 @@ mod tests { // Expected source-order spine: App(App(head, motive_ref), major). let (head_lean, args) = lean_telescope(&decompiled); match head_lean.as_data() { - crate::ix::env::ExprData::Const(name, _, _) => { + ix_common::env::ExprData::Const(name, _, _) => { assert_eq!(*name, head_name); }, other => panic!("expected head Const, got {other:?}"), @@ -4885,7 +4886,7 @@ mod tests { // args[0] is the collapsed motive — must be Const(target), NOT the // decoy lambda from sharing[0]. match args[0].as_data() { - crate::ix::env::ExprData::Const(name, _, _) => { + ix_common::env::ExprData::Const(name, _, _) => { assert_eq!( *name, target_name, "args[0] is the Collapsed motive and must resolve via \ @@ -4921,9 +4922,9 @@ mod tests { // ------------------------------------------------------------------------- #[test] fn test_projection_decompile_loads_meta_extensions() { - use crate::ix::address::Address; - use crate::ix::env::DefinitionSafety; - use crate::ix::ixon::constant::{ + use ix_common::address::Address; + use ix_common::env::DefinitionSafety; + use ixon::constant::{ DefKind, Definition, DefinitionProj, MutConst as IxMutConst, }; @@ -5041,7 +5042,7 @@ mod tests { LeanConstantInfo::DefnInfo(dv) => { let (head_lean, args) = lean_telescope(&dv.value); match head_lean.as_data() { - crate::ix::env::ExprData::Const(name, _, _) => { + ix_common::env::ExprData::Const(name, _, _) => { assert_eq!( *name, head_name, "CallSite head should decode as `head`" @@ -5051,7 +5052,7 @@ mod tests { } assert_eq!(args.len(), 2, "CallSite had 2 entries -> 2 app args"); match args[0].as_data() { - crate::ix::env::ExprData::Const(name, _, _) => { + ix_common::env::ExprData::Const(name, _, _) => { assert_eq!( *name, target_name, "Collapsed arg must resolve via loaded meta_sharing[0]" diff --git a/src/ix/graph.rs b/crates/compile/src/graph.rs similarity index 98% rename from src/ix/graph.rs rename to crates/compile/src/graph.rs index f90c7a95..e10bd777 100644 --- a/src/ix/graph.rs +++ b/crates/compile/src/graph.rs @@ -9,7 +9,7 @@ use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rustc_hash::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry; -use crate::ix::env::{ConstantInfo, Env, Expr, ExprData, Name}; +use ix_common::env::{ConstantInfo, Env, Expr, ExprData, Name}; /// A set of [`Name`]s, used to represent the neighbors of a node in the reference graph. pub type NameSet = FxHashSet; @@ -97,9 +97,7 @@ pub fn build_ref_graph(env: &Env) -> RefGraph { RefGraph { out_refs, in_refs } } -pub(crate) fn get_constant_info_references( - constant_info: &ConstantInfo, -) -> NameSet { +pub fn get_constant_info_references(constant_info: &ConstantInfo) -> NameSet { let cache = &mut FxHashMap::default(); match constant_info { ConstantInfo::AxiomInfo(val) => get_expr_references(&val.cnst.typ, cache), @@ -179,8 +177,8 @@ fn get_expr_references<'a>( #[cfg(test)] mod tests { use super::*; - use crate::ix::env::*; - use lean_ffi::nat::Nat; + use bignat::Nat; + use ix_common::env::*; fn n(s: &str) -> Name { Name::str(Name::anon(), s.to_string()) diff --git a/src/ix/ground.rs b/crates/compile/src/ground.rs similarity index 98% rename from src/ix/ground.rs rename to crates/compile/src/ground.rs index ffe7325a..c854a311 100644 --- a/src/ix/ground.rs +++ b/crates/compile/src/ground.rs @@ -9,15 +9,14 @@ use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rustc_hash::{FxHashMap, FxHashSet}; use std::collections::hash_map::Entry; -use lean_ffi::nat::Nat; +use bignat::Nat; -use crate::{ - ix::env::{ - ConstantInfo, Env, Expr, ExprData, InductiveVal, Level, LevelData, Name, - }, - ix::graph::RefMap, +use ix_common::env::{ + ConstantInfo, Env, Expr, ExprData, InductiveVal, Level, LevelData, Name, }; +use crate::graph::RefMap; + /// Reason a constant failed groundedness checking. /// /// `Indc` carries `InductiveVal + Option` (~360 bytes) — the @@ -235,8 +234,8 @@ fn ground_level( #[cfg(test)] mod tests { use super::*; - use crate::ix::env::*; - use crate::ix::graph::build_ref_graph; + use crate::graph::build_ref_graph; + use ix_common::env::*; fn n(s: &str) -> Name { Name::str(Name::anon(), s.to_string()) diff --git a/src/ix/kernel/egress.rs b/crates/compile/src/kernel_egress.rs similarity index 98% rename from src/ix/kernel/egress.rs rename to crates/compile/src/kernel_egress.rs index 10435cfe..743f97db 100644 --- a/src/ix/kernel/egress.rs +++ b/crates/compile/src/kernel_egress.rs @@ -7,20 +7,20 @@ use rayon::iter::{ }; use rustc_hash::FxHashMap; -use crate::ix::env::{ +use bignat::Nat; +use ix_common::env::{ self, AxiomVal, ConstantInfo as LeanCI, ConstantVal, ConstructorVal, DefinitionVal, InductiveVal, Name, OpaqueVal, QuotVal, RecursorRule as LeanRecRule, RecursorVal, TheoremVal, }; -use crate::ix::ixon::constant::DefKind; -use lean_ffi::nat::Nat; +use ixon::constant::DefKind; -use super::constant::KConst; -use super::env::KEnv; -use super::expr::{ExprData, KExpr, MData}; -use super::id::KId; -use super::level::{KUniv, UnivData}; -use super::mode::Meta; +use ix_kernel::constant::KConst; +use ix_kernel::env::KEnv; +use ix_kernel::expr::{ExprData, KExpr, MData}; +use ix_kernel::id::KId; +use ix_kernel::level::{KUniv, UnivData}; +use ix_kernel::mode::Meta; /// Convert a zero kernel universe to a Lean level. fn egress_level(u: &KUniv, level_params: &[Name]) -> env::Level { @@ -53,7 +53,7 @@ fn egress_levels( } /// Expression egress cache, keyed by content hash. -type Cache = FxHashMap; +type Cache = FxHashMap; /// Convert a zero kernel expression to a Lean expression. fn egress_expr( @@ -343,23 +343,23 @@ use std::sync::Arc; use indexmap::IndexSet; -use crate::ix::address::Address; -use crate::ix::compile::{ +use crate::compile::{ apply_sharing_to_axiom_with_stats, apply_sharing_to_definition_with_stats, apply_sharing_to_mutual_block, apply_sharing_to_quotient_with_stats, apply_sharing_to_recursor_with_stats, }; -use crate::ix::ixon::constant::{ +use ix_common::address::Address; +use ixon::constant::{ Axiom as IxonAxiom, Constant as IxonConstant, ConstantInfo as IxonCI, Constructor as IxonConstructor, ConstructorProj, Definition as IxonDefinition, DefinitionProj, Inductive as IxonInductive, InductiveProj, MutConst as IxonMutConst, Quotient as IxonQuotient, Recursor as IxonRecursor, RecursorProj, RecursorRule as IxonRecursorRule, }; -use crate::ix::ixon::env::{Env as IxonEnv, Named}; -use crate::ix::ixon::expr::Expr as IxonExpr; -use crate::ix::ixon::metadata::ConstantMetaInfo; -use crate::ix::ixon::univ::Univ as IxonUniv; +use ixon::env::{Env as IxonEnv, Named}; +use ixon::expr::Expr as IxonExpr; +use ixon::metadata::ConstantMetaInfo; +use ixon::univ::Univ as IxonUniv; /// Per-constant (or per-block) working context accumulated while converting /// kernel expressions back to Ixon. Mirrors `BlockCache.refs` / `univs` on @@ -1256,14 +1256,17 @@ pub fn ixon_egress( #[cfg(test)] mod tests { use super::*; - use crate::ix::address::Address; - use crate::ix::env::{ + use ix_common::address::Address; + use ix_common::env::{ BinderInfo, DefinitionSafety, ExprData as LeanExprData, Literal, QuotKind, ReducibilityHints, }; - use crate::ix::kernel::constant::RecRule; - use crate::ix::kernel::expr::KExpr; - use crate::ix::kernel::id::KId; + use ix_kernel::constant::{KConst, RecRule}; + use ix_kernel::env::KEnv; + use ix_kernel::expr::KExpr; + use ix_kernel::id::KId; + use ix_kernel::level::KUniv; + use ix_kernel::mode::Meta; fn mk_name(s: &str) -> Name { let mut n = Name::anon(); diff --git a/crates/compile/src/lib.rs b/crates/compile/src/lib.rs new file mode 100644 index 00000000..da38ab96 --- /dev/null +++ b/crates/compile/src/lib.rs @@ -0,0 +1,11 @@ +//! Lean ↔ Ixon compilation pipeline plus kernel ↔ Lean egress. + +pub mod compile; +pub mod condense; +pub mod congruence; +pub mod decompile; +pub mod graph; +pub mod ground; +pub mod kernel_egress; +pub mod mutual; +pub mod store; diff --git a/src/ix/mutual.rs b/crates/compile/src/mutual.rs similarity index 97% rename from src/ix/mutual.rs rename to crates/compile/src/mutual.rs index b3bf8122..b7486a75 100644 --- a/src/ix/mutual.rs +++ b/crates/compile/src/mutual.rs @@ -5,16 +5,15 @@ //! [`ctx_to_all`] / [`all_to_ctx`] functions convert between ordered name //! vectors and index maps. -use lean_ffi::nat::Nat; - -use crate::{ - ix::env::{ - ConstructorVal, DefinitionSafety, DefinitionVal, Expr, InductiveVal, Name, - OpaqueVal, RecursorVal, ReducibilityHints, TheoremVal, - }, - ix::ixon::constant::DefKind, +use bignat::Nat; + +use ix_common::env::{ + ConstructorVal, DefinitionSafety, DefinitionVal, Expr, InductiveVal, Name, + OpaqueVal, RecursorVal, ReducibilityHints, TheoremVal, }; +use ixon::constant::DefKind; + use rustc_hash::FxHashMap; /// A definition-like constant (definition, theorem, or opaque) unified into a @@ -195,7 +194,7 @@ impl MutConst { #[cfg(test)] mod tests { use super::*; - use crate::ix::env::{ConstantVal, Level}; + use ix_common::env::{ConstantVal, Level}; fn n(s: &str) -> Name { Name::str(Name::anon(), s.to_string()) diff --git a/src/ix/store.rs b/crates/compile/src/store.rs similarity index 98% rename from src/ix/store.rs rename to crates/compile/src/store.rs index fe45f508..33dcaf79 100644 --- a/src/ix/store.rs +++ b/crates/compile/src/store.rs @@ -4,7 +4,7 @@ //! are derived from the first 6 hex characters of the Blake3 hash. This provides //! deterministic addressing: identical content always maps to the same path. -use crate::ix::address::Address; +use ix_common::address::Address; use std::env; use std::fs; use std::io; diff --git a/crates/ffi/Cargo.toml b/crates/ffi/Cargo.toml new file mode 100644 index 00000000..aac4f212 --- /dev/null +++ b/crates/ffi/Cargo.toml @@ -0,0 +1,51 @@ +[package] +name = "ix-ffi" +version.workspace = true +edition.workspace = true +license.workspace = true + +[lib] +crate-type = ["lib", "staticlib"] + +[dependencies] +aiur = { workspace = true } +anyhow = { workspace = true } +bignat = { workspace = true } +blake3 = { workspace = true } +dashmap = { workspace = true, features = ["rayon"] } +indexmap = { workspace = true, features = ["rayon"] } +itertools = { workspace = true } +ix-common = { workspace = true } +ix-compile = { workspace = true } +ixon = { workspace = true } +ix-kernel = { workspace = true } +lean-ffi = { workspace = true } +multi-stark = { workspace = true } +mimalloc = { workspace = true } +num-bigint = { workspace = true } +rayon = { workspace = true } +rustc-hash = { workspace = true } +sha2 = { workspace = true } +tiny-keccak = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +tracing-texray = { workspace = true } + +# Iroh dependencies +bytes = { version = "1.10.1", optional = true } +tokio = { version = "1.44.1", optional = true } +iroh = { version = "0.97", optional = true } +iroh-base = { version = "0.97", optional = true } +n0-error = { version = "0.1", optional = true } +getrandom = { version = "0.3", optional = true } +bincode = { version = "2.0.1", optional = true } +serde = { version = "1.0.219", features = ["derive"], optional = true } + +[features] +default = [] +parallel = ["aiur/parallel"] +test-ffi = [] +net = ["bytes", "tokio", "iroh", "iroh-base", "n0-error", "getrandom", "bincode", "serde"] + +[lints] +workspace = true diff --git a/src/ffi/_iroh.rs b/crates/ffi/src/_iroh.rs similarity index 100% rename from src/ffi/_iroh.rs rename to crates/ffi/src/_iroh.rs diff --git a/src/ffi/aiur.rs b/crates/ffi/src/aiur.rs similarity index 95% rename from src/ffi/aiur.rs rename to crates/ffi/src/aiur.rs index aa565fd2..01ad45ac 100644 --- a/src/ffi/aiur.rs +++ b/crates/ffi/src/aiur.rs @@ -3,7 +3,7 @@ use multi_stark::p3_field::integers::QuotientMap; pub mod protocol; pub mod toplevel; -use crate::aiur::G; +use aiur::G; use lean_ffi::object::LeanRef; #[inline] diff --git a/src/ffi/aiur/protocol.rs b/crates/ffi/src/aiur/protocol.rs similarity index 97% rename from src/ffi/aiur/protocol.rs rename to crates/ffi/src/aiur/protocol.rs index ed2ec7b4..6f323249 100644 --- a/src/ffi/aiur/protocol.rs +++ b/crates/ffi/src/aiur/protocol.rs @@ -12,18 +12,16 @@ use lean_ffi::object::{ }; use crate::{ - aiur::{ - G, - execute::{IOBuffer, IOKeyInfo}, - synthesis::AiurSystem, - }, - ffi::aiur::{ - lean_unbox_g, lean_unbox_nat_as_usize, toplevel::decode_toplevel, - }, + aiur::{lean_unbox_g, lean_unbox_nat_as_usize, toplevel::decode_toplevel}, lean::{ LeanAiurCommitmentParameters, LeanAiurFriParameters, LeanAiurToplevel, }, }; +use aiur::{ + G, + execute::{IOBuffer, IOKeyInfo}, + synthesis::AiurSystem, +}; // ============================================================================= // External class registration @@ -121,7 +119,7 @@ extern "C" fn rs_aiur_toplevel_execute( let mut query_counts: Vec<(usize, usize)> = Vec::with_capacity( query_record.function_queries.len() + toplevel.memory_sizes.len(), ); - let summarize = |q: &crate::aiur::execute::QueryMap| -> (usize, usize) { + let summarize = |q: &aiur::execute::QueryMap| -> (usize, usize) { let mut rows = 0usize; let mut hits = 0usize; for (_, res) in q.iter() { diff --git a/src/ffi/aiur/toplevel.rs b/crates/ffi/src/aiur/toplevel.rs similarity index 97% rename from src/ffi/aiur/toplevel.rs rename to crates/ffi/src/aiur/toplevel.rs index d2b75a22..072e2203 100644 --- a/src/ffi/aiur/toplevel.rs +++ b/crates/ffi/src/aiur/toplevel.rs @@ -4,16 +4,13 @@ use lean_ffi::object::{LeanBorrowed, LeanCtor, LeanRef}; use crate::lean::LeanAiurFunction; -use crate::{ - FxIndexMap, - aiur::{ - G, - bytecode::{Block, Ctrl, Function, FunctionLayout, Op, Toplevel, ValIdx}, - }, - lean::LeanAiurToplevel, +use crate::lean::LeanAiurToplevel; +use aiur::{ + FxIndexMap, G, + bytecode::{Block, Ctrl, Function, FunctionLayout, Op, Toplevel, ValIdx}, }; -use crate::ffi::aiur::{lean_unbox_g, lean_unbox_nat_as_usize}; +use crate::aiur::{lean_unbox_g, lean_unbox_nat_as_usize}; fn decode_vec_val_idx(obj: LeanBorrowed<'_>) -> Vec { obj.as_array().map(|x| lean_unbox_nat_as_usize(&x)) diff --git a/src/ffi/builder.rs b/crates/ffi/src/builder.rs similarity index 100% rename from src/ffi/builder.rs rename to crates/ffi/src/builder.rs diff --git a/src/ffi/byte_array.rs b/crates/ffi/src/byte_array.rs similarity index 100% rename from src/ffi/byte_array.rs rename to crates/ffi/src/byte_array.rs diff --git a/src/ffi/compile.rs b/crates/ffi/src/compile.rs similarity index 97% rename from src/ffi/compile.rs rename to crates/ffi/src/compile.rs index b91e19c3..cf928511 100644 --- a/src/ffi/compile.rs +++ b/crates/ffi/src/compile.rs @@ -9,44 +9,44 @@ use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::compile::{ - CompileOptions, CompileState, compile_env_with_options, -}; -use crate::ix::condense::compute_sccs; -use crate::ix::decompile::decompile_env; -use crate::ix::env::Name; -use crate::ix::graph::build_ref_graph; -use crate::ix::ixon::constant::Constant as IxonConstant; -#[cfg(feature = "test-ffi")] -use crate::ix::ixon::constant::ConstantInfo; -#[cfg(feature = "test-ffi")] -use crate::ix::ixon::expr::Expr as IxonExpr; -use crate::ix::ixon::{Comm, ConstantMeta}; use crate::lean::{ LeanIxBlock, LeanIxCompileError, LeanIxCompilePhases, LeanIxCondensedBlocks, LeanIxConstantInfo, LeanIxDecompileError, LeanIxName, LeanIxRawEnvironment, LeanIxSerializeError, LeanIxonRawBlob, LeanIxonRawComm, LeanIxonRawConst, LeanIxonRawEnv, LeanIxonRawNameEntry, LeanIxonRawNamed, }; -use lean_ffi::nat::Nat; +use ix_common::address::Address; +use ix_common::env::Name; +use ix_compile::compile::{ + CompileOptions, CompileState, compile_env_with_options, +}; +use ix_compile::condense::compute_sccs; +use ix_compile::decompile::decompile_env; +use ix_compile::graph::build_ref_graph; +use ixon::constant::Constant as IxonConstant; +#[cfg(feature = "test-ffi")] +use ixon::constant::ConstantInfo; +#[cfg(feature = "test-ffi")] +use ixon::expr::Expr as IxonExpr; +use ixon::{Comm, ConstantMeta}; use lean_ffi::object::LeanIOResult; +use lean_ffi::object::LeanNat; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanByteArray, LeanExcept, LeanList, LeanOwned, LeanProd, LeanRef, LeanString, }; -use crate::ffi::builder::LeanBuildCache; -use crate::ffi::ixon::env::decoded_to_ixon_env; -use crate::ffi::lean_env::decode_env; +use crate::builder::LeanBuildCache; use crate::lean::LeanIxAddress; +use crate::lean_env::decode_env; +use crate::lean_ixon::env::decoded_to_ixon_env; #[cfg(feature = "test-ffi")] -use crate::ffi::lean_env::{GlobalCache, decode_name}; +use crate::lean::{LeanIxBlockCompareDetail, LeanIxBlockCompareResult}; #[cfg(feature = "test-ffi")] -use crate::ix::ixon::serialize::put_expr; +use crate::lean_env::{GlobalCache, decode_name}; #[cfg(feature = "test-ffi")] -use crate::lean::{LeanIxBlockCompareDetail, LeanIxBlockCompareResult}; +use ixon::serialize::put_expr; #[cfg(feature = "test-ffi")] use std::collections::HashMap; @@ -1002,17 +1002,17 @@ extern "C" fn rs_get_pre_sharing_exprs( let mut exprs = Vec::new(); for mc in muts { match mc { - crate::ix::ixon::constant::MutConst::Defn(def) => { + ixon::constant::MutConst::Defn(def) => { exprs.push(def.typ.clone()); exprs.push(def.value.clone()); }, - crate::ix::ixon::constant::MutConst::Indc(ind) => { + ixon::constant::MutConst::Indc(ind) => { exprs.push(ind.typ.clone()); for ctor in &ind.ctors { exprs.push(ctor.typ.clone()); } }, - crate::ix::ixon::constant::MutConst::Recr(rec) => { + ixon::constant::MutConst::Recr(rec) => { exprs.push(rec.typ.clone()); for rule in &rec.rules { exprs.push(rule.rhs.clone()); @@ -1091,13 +1091,9 @@ extern "C" fn rs_get_pre_sharing_exprs_len( let mut count = 0; for mc in muts { match mc { - crate::ix::ixon::constant::MutConst::Defn(_) => count += 2, - crate::ix::ixon::constant::MutConst::Indc(ind) => { - count += 1 + ind.ctors.len() - }, - crate::ix::ixon::constant::MutConst::Recr(rec) => { - count += 1 + rec.rules.len() - }, + ixon::constant::MutConst::Defn(_) => count += 2, + ixon::constant::MutConst::Indc(ind) => count += 1 + ind.ctors.len(), + ixon::constant::MutConst::Recr(rec) => count += 1 + rec.rules.len(), } } count @@ -1155,7 +1151,7 @@ extern "C" fn rs_get_compiled_const_count( // Error type FFI builders // ============================================================================= -use crate::ix::ixon::error::{CompileError, DecompileError, SerializeError}; +use ixon::error::{CompileError, DecompileError, SerializeError}; impl LeanIxSerializeError { /// Build a Lean Ixon.SerializeError from a Rust SerializeError. @@ -1244,7 +1240,7 @@ impl LeanIxSerializeError { }, 5 => SerializeError::AddressError, 6 => { - let max = Nat::from_obj(&self.get_obj(0)) + let max = LeanNat::to_nat(&self.get_obj(0)) .to_u64() .and_then(|x| usize::try_from(x).ok()) .unwrap_or(0); @@ -1335,7 +1331,7 @@ impl LeanIxDecompileError { pub fn decode(&self) -> DecompileError { match self.as_ctor().tag() { 0 => { - let refs_len = Nat::from_obj(&self.get_obj(0)) + let refs_len = LeanNat::to_nat(&self.get_obj(0)) .to_u64() .and_then(|x| usize::try_from(x).ok()) .unwrap_or(0); @@ -1344,7 +1340,7 @@ impl LeanIxDecompileError { DecompileError::InvalidRefIndex { idx, refs_len, constant } }, 1 => { - let univs_len = Nat::from_obj(&self.get_obj(0)) + let univs_len = LeanNat::to_nat(&self.get_obj(0)) .to_u64() .and_then(|x| usize::try_from(x).ok()) .unwrap_or(0); @@ -1353,7 +1349,7 @@ impl LeanIxDecompileError { DecompileError::InvalidUnivIndex { idx, univs_len, constant } }, 2 => { - let max = Nat::from_obj(&self.get_obj(0)) + let max = LeanNat::to_nat(&self.get_obj(0)) .to_u64() .and_then(|x| usize::try_from(x).ok()) .unwrap_or(0); @@ -1362,7 +1358,7 @@ impl LeanIxDecompileError { DecompileError::InvalidShareIndex { idx, max, constant } }, 3 => { - let ctx_size = Nat::from_obj(&self.get_obj(0)) + let ctx_size = LeanNat::to_nat(&self.get_obj(0)) .to_u64() .and_then(|x| usize::try_from(x).ok()) .unwrap_or(0); @@ -1371,7 +1367,7 @@ impl LeanIxDecompileError { DecompileError::InvalidRecIndex { idx, ctx_size, constant } }, 4 => { - let max = Nat::from_obj(&self.get_obj(0)) + let max = LeanNat::to_nat(&self.get_obj(0)) .to_u64() .and_then(|x| usize::try_from(x).ok()) .unwrap_or(0); diff --git a/src/ffi/graph.rs b/crates/ffi/src/graph.rs similarity index 94% rename from src/ffi/graph.rs rename to crates/ffi/src/graph.rs index acfcacff..5dfdd9e8 100644 --- a/src/ffi/graph.rs +++ b/crates/ffi/src/graph.rs @@ -2,21 +2,21 @@ use std::sync::Arc; -use crate::ix::condense::compute_sccs; -use crate::ix::graph::build_ref_graph; use crate::lean::LeanIxCondensedBlocks; +use ix_compile::condense::compute_sccs; +use ix_compile::graph::build_ref_graph; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanIOResult, LeanList, LeanOwned, LeanProd, }; -use crate::ffi::builder::LeanBuildCache; -use crate::ffi::lean_env::decode_env; +use crate::builder::LeanBuildCache; use crate::lean::LeanIxName; +use crate::lean_env::decode_env; /// Build an Array (Ix.Name × Array Ix.Name) from a RefMap. pub fn build_ref_graph_array( cache: &mut LeanBuildCache, - refs: &crate::ix::graph::RefMap, + refs: &ix_compile::graph::RefMap, ) -> LeanArray { let arr = LeanArray::alloc(refs.len()); for (i, (name, ref_set)) in refs.iter().enumerate() { @@ -38,7 +38,7 @@ impl LeanIxCondensedBlocks { /// Build a RustCondensedBlocks structure. pub fn build( cache: &mut LeanBuildCache, - condensed: &crate::ix::condense::CondensedBlocks, + condensed: &ix_compile::condense::CondensedBlocks, ) -> Self { // Build lowLinks: Array (Ix.Name × Ix.Name) let low_links_arr = LeanArray::alloc(condensed.low_links.len()); diff --git a/src/iroh.rs b/crates/ffi/src/iroh.rs similarity index 100% rename from src/iroh.rs rename to crates/ffi/src/iroh.rs diff --git a/src/iroh/client.rs b/crates/ffi/src/iroh/client.rs similarity index 100% rename from src/iroh/client.rs rename to crates/ffi/src/iroh/client.rs diff --git a/src/iroh/server.rs b/crates/ffi/src/iroh/server.rs similarity index 100% rename from src/iroh/server.rs rename to crates/ffi/src/iroh/server.rs diff --git a/src/ffi/ix.rs b/crates/ffi/src/ix.rs similarity index 100% rename from src/ffi/ix.rs rename to crates/ffi/src/ix.rs diff --git a/src/ffi/ix/address.rs b/crates/ffi/src/ix/address.rs similarity index 98% rename from src/ffi/ix/address.rs rename to crates/ffi/src/ix/address.rs index f389f8d1..34512e45 100644 --- a/src/ffi/ix/address.rs +++ b/crates/ffi/src/ix/address.rs @@ -2,8 +2,8 @@ //! //! Address = { hash : ByteArray } - ByteArray wrapper for blake3 Hash -use crate::ix::address::Address; use crate::lean::LeanIxAddress; +use ix_common::address::Address; use lean_ffi::object::{LeanArray, LeanBorrowed, LeanByteArray, LeanOwned}; impl LeanIxAddress { diff --git a/src/ffi/ix/constant.rs b/crates/ffi/src/ix/constant.rs similarity index 91% rename from src/ffi/ix/constant.rs rename to crates/ffi/src/ix/constant.rs index ebc01d8c..5c3fb70a 100644 --- a/src/ffi/ix/constant.rs +++ b/crates/ffi/src/ix/constant.rs @@ -10,23 +10,23 @@ //! - Tag 6: ctorInfo (v : ConstructorVal) //! - Tag 7: recInfo (v : RecursorVal) -use crate::ix::env::{ - AxiomVal, ConstantInfo, ConstantVal, ConstructorVal, DefinitionSafety, - DefinitionVal, InductiveVal, Name, OpaqueVal, QuotKind, QuotVal, - RecursorRule, RecursorVal, ReducibilityHints, TheoremVal, -}; use crate::lean::{ LeanIxAxiomVal, LeanIxConstantInfo, LeanIxConstantVal, LeanIxConstructorVal, LeanIxDefinitionVal, LeanIxExpr, LeanIxInductiveVal, LeanIxName, LeanIxOpaqueVal, LeanIxQuotVal, LeanIxRecursorRule, LeanIxRecursorVal, LeanIxReducibilityHints, LeanIxTheoremVal, }; -use lean_ffi::nat::Nat; +use ix_common::env::{ + AxiomVal, ConstantInfo, ConstantVal, ConstructorVal, DefinitionSafety, + DefinitionVal, InductiveVal, Name, OpaqueVal, QuotKind, QuotVal, + RecursorRule, RecursorVal, ReducibilityHints, TheoremVal, +}; #[cfg(feature = "test-ffi")] use lean_ffi::object::LeanBorrowed; +use lean_ffi::object::LeanNat; use lean_ffi::object::{LeanArray, LeanOwned, LeanRef}; -use crate::ffi::builder::LeanBuildCache; +use crate::builder::LeanBuildCache; // ============================================================================= // ConstantVal @@ -121,7 +121,7 @@ impl LeanIxRecursorRule { let ctor = self.as_ctor(); RecursorRule { ctor: LeanIxName(ctor.get(0)).decode(), - n_fields: Nat::from_obj(&ctor.get(1)), + n_fields: LeanNat::to_nat(&ctor.get(1)), rhs: LeanIxExpr(ctor.get(2)).decode(), } } @@ -141,7 +141,7 @@ impl LeanIxRecursorRule { for (i, rule) in rules.iter().enumerate() { // RecursorRule = { ctor : Name, nFields : Nat, rhs : Expr } let ctor_obj = LeanIxName::build(cache, &rule.ctor); - let n_fields_obj = Nat::to_lean(&rule.n_fields); + let n_fields_obj = LeanNat::from_nat(&rule.n_fields); let rhs_obj = LeanIxExpr::build(cache, &rule.rhs); let rule_obj = LeanIxRecursorRule::alloc(0); @@ -253,11 +253,11 @@ impl LeanIxConstantInfo { ConstantInfo::InductInfo(v) => { // InductiveVal = { cnst, numParams, numIndices, all, ctors, numNested, isRec, isUnsafe, isReflexive } let cnst_obj = LeanIxConstantVal::build(cache, &v.cnst); - let num_params_obj = Nat::to_lean(&v.num_params); - let num_indices_obj = Nat::to_lean(&v.num_indices); + let num_params_obj = LeanNat::from_nat(&v.num_params); + let num_indices_obj = LeanNat::from_nat(&v.num_indices); let all_obj = LeanIxName::build_array(cache, &v.all); let ctors_obj = LeanIxName::build_array(cache, &v.ctors); - let num_nested_obj = Nat::to_lean(&v.num_nested); + let num_nested_obj = LeanNat::from_nat(&v.num_nested); // 6 object fields, 3 scalar bytes for bools let induct_val = LeanIxInductiveVal::alloc(0); @@ -280,9 +280,9 @@ impl LeanIxConstantInfo { // ConstructorVal = { cnst, induct, cidx, numParams, numFields, isUnsafe } let cnst_obj = LeanIxConstantVal::build(cache, &v.cnst); let induct_obj = LeanIxName::build(cache, &v.induct); - let cidx_obj = Nat::to_lean(&v.cidx); - let num_params_obj = Nat::to_lean(&v.num_params); - let num_fields_obj = Nat::to_lean(&v.num_fields); + let cidx_obj = LeanNat::from_nat(&v.cidx); + let num_params_obj = LeanNat::from_nat(&v.num_params); + let num_fields_obj = LeanNat::from_nat(&v.num_fields); // 5 object fields, 1 scalar byte for bool let ctor_val = LeanIxConstructorVal::alloc(0); @@ -302,10 +302,10 @@ impl LeanIxConstantInfo { // RecursorVal = { cnst, all, numParams, numIndices, numMotives, numMinors, rules, k, isUnsafe } let cnst_obj = LeanIxConstantVal::build(cache, &v.cnst); let all_obj = LeanIxName::build_array(cache, &v.all); - let num_params_obj = Nat::to_lean(&v.num_params); - let num_indices_obj = Nat::to_lean(&v.num_indices); - let num_motives_obj = Nat::to_lean(&v.num_motives); - let num_minors_obj = Nat::to_lean(&v.num_minors); + let num_params_obj = LeanNat::from_nat(&v.num_params); + let num_indices_obj = LeanNat::from_nat(&v.num_indices); + let num_motives_obj = LeanNat::from_nat(&v.num_motives); + let num_minors_obj = LeanNat::from_nat(&v.num_minors); let rules_obj = LeanIxRecursorRule::build_array(cache, &v.rules); // 7 object fields, 2 scalar bytes for bools @@ -404,11 +404,11 @@ impl LeanIxConstantInfo { ConstantInfo::InductInfo(InductiveVal { cnst: LeanIxConstantVal(inner_val.get_obj(0)).decode(), - num_params: Nat::from_obj(&inner_val.get_obj(1)), - num_indices: Nat::from_obj(&inner_val.get_obj(2)), + num_params: LeanNat::to_nat(&inner_val.get_obj(1)), + num_indices: LeanNat::to_nat(&inner_val.get_obj(2)), all: LeanIxName::decode_array(inner_val.get_obj(3).as_array()), ctors: LeanIxName::decode_array(inner_val.get_obj(4).as_array()), - num_nested: Nat::from_obj(&inner_val.get_obj(5)), + num_nested: LeanNat::to_nat(&inner_val.get_obj(5)), is_rec, is_unsafe, is_reflexive, @@ -421,9 +421,9 @@ impl LeanIxConstantInfo { ConstantInfo::CtorInfo(ConstructorVal { cnst: LeanIxConstantVal(inner_val.get_obj(0)).decode(), induct: LeanIxName(inner_val.get_obj(1)).decode(), - cidx: Nat::from_obj(&inner_val.get_obj(2)), - num_params: Nat::from_obj(&inner_val.get_obj(3)), - num_fields: Nat::from_obj(&inner_val.get_obj(4)), + cidx: LeanNat::to_nat(&inner_val.get_obj(2)), + num_params: LeanNat::to_nat(&inner_val.get_obj(3)), + num_fields: LeanNat::to_nat(&inner_val.get_obj(4)), is_unsafe, }) }, @@ -440,10 +440,10 @@ impl LeanIxConstantInfo { ConstantInfo::RecInfo(RecursorVal { cnst: LeanIxConstantVal(inner_val.get_obj(0)).decode(), all: LeanIxName::decode_array(inner_val.get_obj(1).as_array()), - num_params: Nat::from_obj(&inner_val.get_obj(2)), - num_indices: Nat::from_obj(&inner_val.get_obj(3)), - num_motives: Nat::from_obj(&inner_val.get_obj(4)), - num_minors: Nat::from_obj(&inner_val.get_obj(5)), + num_params: LeanNat::to_nat(&inner_val.get_obj(2)), + num_indices: LeanNat::to_nat(&inner_val.get_obj(3)), + num_motives: LeanNat::to_nat(&inner_val.get_obj(4)), + num_minors: LeanNat::to_nat(&inner_val.get_obj(5)), rules, k, is_unsafe, diff --git a/src/ffi/ix/data.rs b/crates/ffi/src/ix/data.rs similarity index 92% rename from src/ffi/ix/data.rs rename to crates/ffi/src/ix/data.rs index 7fbb6228..355be8bb 100644 --- a/src/ffi/ix/data.rs +++ b/crates/ffi/src/ix/data.rs @@ -1,18 +1,18 @@ //! Ix.DataValue, Ix.Syntax, Ix.SourceInfo build/decode/roundtrip FFI. -use crate::ix::env::{ - DataValue, Int, Name, SourceInfo, Substring, Syntax, SyntaxPreresolved, -}; use crate::lean::{ LeanIxDataValue, LeanIxInt, LeanIxName, LeanIxSourceInfo, LeanIxSubstring, LeanIxSyntax, LeanIxSyntaxPreresolved, }; -use lean_ffi::nat::Nat; +use ix_common::env::{ + DataValue, Int, Name, SourceInfo, Substring, Syntax, SyntaxPreresolved, +}; #[cfg(feature = "test-ffi")] use lean_ffi::object::LeanBorrowed; +use lean_ffi::object::LeanNat; use lean_ffi::object::{LeanArray, LeanOwned, LeanProd, LeanRef, LeanString}; -use crate::ffi::builder::LeanBuildCache; +use crate::builder::LeanBuildCache; impl LeanIxInt { /// Build a Ix.Int (ofNat or negSucc). @@ -20,12 +20,12 @@ impl LeanIxInt { match int { Int::OfNat(n) => { let ctor = LeanIxInt::alloc(0); - ctor.set_obj(0, Nat::to_lean(n)); + ctor.set_obj(0, LeanNat::from_nat(n)); ctor }, Int::NegSucc(n) => { let ctor = LeanIxInt::alloc(1); - ctor.set_obj(0, Nat::to_lean(n)); + ctor.set_obj(0, LeanNat::from_nat(n)); ctor }, } @@ -37,7 +37,7 @@ impl LeanIxInt { /// Ix.Int: ofNat (tag 0, 1 field) | negSucc (tag 1, 1 field) pub fn decode(&self) -> Int { let ctor = self.as_ctor(); - let nat = Nat::from_obj(&ctor.get(0)); + let nat = LeanNat::to_nat(&ctor.get(0)); match ctor.tag() { 0 => Int::OfNat(nat), 1 => Int::NegSucc(nat), @@ -51,8 +51,8 @@ impl LeanIxSubstring { pub fn build(ss: &Substring) -> Self { let ctor = LeanIxSubstring::alloc(0); ctor.set_obj(0, LeanString::new(ss.str.as_str())); - ctor.set_obj(1, Nat::to_lean(&ss.start_pos)); - ctor.set_obj(2, Nat::to_lean(&ss.stop_pos)); + ctor.set_obj(1, LeanNat::from_nat(&ss.start_pos)); + ctor.set_obj(2, LeanNat::from_nat(&ss.stop_pos)); ctor } } @@ -63,8 +63,8 @@ impl LeanIxSubstring { let ctor = self.as_ctor(); Substring { str: ctor.get(0).as_string().to_string(), - start_pos: Nat::from_obj(&ctor.get(1)), - stop_pos: Nat::from_obj(&ctor.get(2)), + start_pos: LeanNat::to_nat(&ctor.get(1)), + stop_pos: LeanNat::to_nat(&ctor.get(2)), } } } @@ -77,16 +77,16 @@ impl LeanIxSourceInfo { SourceInfo::Original(leading, pos, trailing, end_pos) => { let ctor = LeanIxSourceInfo::alloc(0); ctor.set_obj(0, LeanIxSubstring::build(leading)); - ctor.set_obj(1, Nat::to_lean(pos)); + ctor.set_obj(1, LeanNat::from_nat(pos)); ctor.set_obj(2, LeanIxSubstring::build(trailing)); - ctor.set_obj(3, Nat::to_lean(end_pos)); + ctor.set_obj(3, LeanNat::from_nat(end_pos)); ctor }, // | synthetic (pos : Nat) (endPos : Nat) (canonical : Bool) -- tag 1 SourceInfo::Synthetic(pos, end_pos, canonical) => { let ctor = LeanIxSourceInfo::alloc(1); - ctor.set_obj(0, Nat::to_lean(pos)); - ctor.set_obj(1, Nat::to_lean(end_pos)); + ctor.set_obj(0, LeanNat::from_nat(pos)); + ctor.set_obj(1, LeanNat::from_nat(end_pos)); ctor.set_num_8(0, u8::from(*canonical)); ctor }, @@ -108,9 +108,9 @@ impl LeanIxSourceInfo { // original SourceInfo::Original( LeanIxSubstring(ctor.get(0)).decode(), - Nat::from_obj(&ctor.get(1)), + LeanNat::to_nat(&ctor.get(1)), LeanIxSubstring(ctor.get(2)).decode(), - Nat::from_obj(&ctor.get(3)), + LeanNat::to_nat(&ctor.get(3)), ) }, 1 => { @@ -118,8 +118,8 @@ impl LeanIxSourceInfo { let canonical = self.get_num_8(0) != 0; SourceInfo::Synthetic( - Nat::from_obj(&self.get_obj(0)), - Nat::from_obj(&self.get_obj(1)), + LeanNat::to_nat(&self.get_obj(0)), + LeanNat::to_nat(&self.get_obj(1)), canonical, ) }, @@ -298,7 +298,7 @@ impl LeanIxDataValue { }, DataValue::OfNat(n) => { let ctor = LeanIxDataValue::alloc(3); - ctor.set_obj(0, Nat::to_lean(n)); + ctor.set_obj(0, LeanNat::from_nat(n)); ctor }, DataValue::OfInt(i) => { @@ -351,13 +351,13 @@ impl LeanIxDataValue { }, 3 => { // ofNat: 1 object field - DataValue::OfNat(Nat::from_obj(&ctor.get(0))) + DataValue::OfNat(LeanNat::to_nat(&ctor.get(0))) }, 4 => { // ofInt: 1 object field let inner = ctor.get(0); let inner_ctor = inner.as_ctor(); - let nat = Nat::from_obj(&inner_ctor.get(0)); + let nat = LeanNat::to_nat(&inner_ctor.get(0)); match inner_ctor.tag() { 0 => DataValue::OfInt(Int::OfNat(nat)), 1 => DataValue::OfInt(Int::NegSucc(nat)), diff --git a/src/ffi/ix/env.rs b/crates/ffi/src/ix/env.rs similarity index 97% rename from src/ffi/ix/env.rs rename to crates/ffi/src/ix/env.rs index c4179fe2..3800bc61 100644 --- a/src/ffi/ix/env.rs +++ b/crates/ffi/src/ix/env.rs @@ -2,15 +2,15 @@ use rustc_hash::FxHashMap; -use crate::ix::env::{ConstantInfo, Name}; use crate::lean::{ LeanIxConstantInfo, LeanIxEnvironment, LeanIxName, LeanIxRawEnvironment, }; +use ix_common::env::{ConstantInfo, Name}; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanCtor, LeanOwned, LeanProd, LeanRef, }; -use crate::ffi::builder::LeanBuildCache; +use crate::builder::LeanBuildCache; // ============================================================================= // HashMap Building @@ -140,7 +140,7 @@ impl LeanIxRawEnvironment { /// so we return just the array, not a structure containing it. pub fn build( cache: &mut LeanBuildCache, - consts: &crate::ix::env::Env, + consts: &ix_common::env::Env, ) -> Self { // Build consts array: Array (Name × ConstantInfo) let consts_arr = LeanArray::alloc(consts.len()); @@ -242,7 +242,7 @@ pub extern "C" fn rs_roundtrip_ix_environment( env_ptr: LeanIxEnvironment>, ) -> LeanIxRawEnvironment { let decoded = env_ptr.decode(); - let env: crate::ix::env::Env = decoded.into_iter().collect(); + let env: ix_common::env::Env = decoded.into_iter().collect(); let mut cache = LeanBuildCache::with_capacity(env.len()); LeanIxRawEnvironment::build(&mut cache, &env) } diff --git a/src/ffi/ix/expr.rs b/crates/ffi/src/ix/expr.rs similarity index 96% rename from src/ffi/ix/expr.rs rename to crates/ffi/src/ix/expr.rs index ced0bb75..4b5e4bfc 100644 --- a/src/ffi/ix/expr.rs +++ b/crates/ffi/src/ix/expr.rs @@ -14,18 +14,18 @@ //! - Tag 10: mdata (data : Array (Name × DataValue)) (expr : Expr) (hash : Address) //! - Tag 11: proj (typeName : Name) (idx : Nat) (struct : Expr) (hash : Address) -use crate::ffi::builder::LeanBuildCache; -use crate::ix::env::{ - BinderInfo, DataValue, Expr, ExprData, Level, Literal, Name, -}; +use crate::builder::LeanBuildCache; use crate::lean::LeanIxAddress; use crate::lean::{ LeanIxBinderInfo, LeanIxDataValue, LeanIxExpr, LeanIxLevel, LeanIxLiteral, LeanIxName, }; -use lean_ffi::nat::Nat; +use ix_common::env::{ + BinderInfo, DataValue, Expr, ExprData, Level, Literal, Name, +}; #[cfg(feature = "test-ffi")] use lean_ffi::object::LeanBorrowed; +use lean_ffi::object::LeanNat; use lean_ffi::object::{LeanOwned, LeanRef, LeanString}; impl LeanIxExpr { @@ -40,7 +40,7 @@ impl LeanIxExpr { let result = match expr.as_data() { ExprData::Bvar(idx, h) => { let ctor = LeanIxExpr::alloc(0); - ctor.set_obj(0, Nat::to_lean(idx)); + ctor.set_obj(0, LeanNat::from_nat(idx)); ctor.set_obj(1, LeanIxAddress::build_from_hash(h)); ctor }, @@ -139,7 +139,7 @@ impl LeanIxExpr { }, ExprData::Proj(type_name, idx, struct_expr, h) => { let name_obj = LeanIxName::build(cache, type_name); - let idx_obj = Nat::to_lean(idx); + let idx_obj = LeanNat::from_nat(idx); let struct_obj = Self::build(cache, struct_expr); let ctor = LeanIxExpr::alloc(11); ctor.set_obj(0, name_obj); @@ -162,7 +162,7 @@ impl LeanIxExpr { match ctor.tag() { 0 => { // bvar - let idx = Nat::from_obj(&ctor.get(0)); + let idx = LeanNat::to_nat(&ctor.get(0)); Expr::bvar(idx) }, 1 => { @@ -247,7 +247,7 @@ impl LeanIxExpr { 11 => { // proj: typeName, idx, struct, hash let type_name = LeanIxName(ctor.get(0)).decode(); - let idx = Nat::from_obj(&ctor.get(1)); + let idx = LeanNat::to_nat(&ctor.get(1)); let struct_expr = LeanIxExpr(ctor.get(2)).decode(); Expr::proj(type_name, idx, struct_expr) @@ -263,7 +263,7 @@ impl LeanIxLiteral { match lit { Literal::NatVal(n) => { let ctor = LeanIxLiteral::alloc(0); - ctor.set_obj(0, Nat::to_lean(n)); + ctor.set_obj(0, LeanNat::from_nat(n)); ctor }, Literal::StrVal(s) => { @@ -282,7 +282,7 @@ impl LeanIxLiteral { match ctor.tag() { 0 => { // natVal - let nat = Nat::from_obj(&ctor.get(0)); + let nat = LeanNat::to_nat(&ctor.get(0)); Literal::NatVal(nat) }, 1 => { diff --git a/src/ffi/ix/level.rs b/crates/ffi/src/ix/level.rs similarity index 98% rename from src/ffi/ix/level.rs rename to crates/ffi/src/ix/level.rs index 5039c386..fead881f 100644 --- a/src/ffi/ix/level.rs +++ b/crates/ffi/src/ix/level.rs @@ -8,11 +8,11 @@ //! - Tag 4: param (n : Name) (hash : Address) //! - Tag 5: mvar (n : Name) (hash : Address) -use crate::ix::env::{Level, LevelData}; use crate::lean::{LeanIxLevel, LeanIxName}; +use ix_common::env::{Level, LevelData}; use lean_ffi::object::{LeanArray, LeanBorrowed, LeanOwned, LeanRef}; -use crate::ffi::builder::LeanBuildCache; +use crate::builder::LeanBuildCache; use crate::lean::LeanIxAddress; impl LeanIxLevel { diff --git a/src/ffi/ix/name.rs b/crates/ffi/src/ix/name.rs similarity index 94% rename from src/ffi/ix/name.rs rename to crates/ffi/src/ix/name.rs index 62e72ec0..be359723 100644 --- a/src/ffi/ix/name.rs +++ b/crates/ffi/src/ix/name.rs @@ -5,14 +5,14 @@ //! - Tag 1: str (parent : Name) (s : String) (hash : Address) //! - Tag 2: num (parent : Name) (i : Nat) (hash : Address) -use crate::ix::env::{Name, NameData}; use crate::lean::LeanIxName; -use lean_ffi::nat::Nat; +use ix_common::env::{Name, NameData}; +use lean_ffi::object::LeanNat; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanOwned, LeanRef, LeanString, }; -use crate::ffi::builder::LeanBuildCache; +use crate::builder::LeanBuildCache; use crate::lean::LeanIxAddress; impl LeanIxName { @@ -41,7 +41,7 @@ impl LeanIxName { }, NameData::Num(parent, n, h) => { let parent_obj = Self::build(cache, parent); - let n_obj = Nat::to_lean(n); + let n_obj = LeanNat::from_nat(n); let ctor = LeanIxName::alloc(2); ctor.set_obj(0, parent_obj); ctor.set_obj(1, n_obj); @@ -85,7 +85,7 @@ impl LeanIxName { 2 => { // num: parent, i, hash let parent = LeanIxName(ctor.get(0)).decode(); - let i = Nat::from_obj(&ctor.get(1)); + let i = LeanNat::to_nat(&ctor.get(1)); Name::num(parent, i) }, _ => panic!("Invalid Ix.Name tag: {}", ctor.tag()), diff --git a/src/ffi/keccak.rs b/crates/ffi/src/keccak.rs similarity index 100% rename from src/ffi/keccak.rs rename to crates/ffi/src/keccak.rs diff --git a/src/ffi/kernel.rs b/crates/ffi/src/kernel.rs similarity index 95% rename from src/ffi/kernel.rs rename to crates/ffi/src/kernel.rs index 84ba7d84..1e2e5eb9 100644 --- a/src/ffi/kernel.rs +++ b/crates/ffi/src/kernel.rs @@ -37,7 +37,7 @@ use std::thread; use std::time::{Duration, Instant}; use lean_ffi::include::lean_object; -use lean_ffi::nat::Nat; +use lean_ffi::object::LeanNat; use rustc_hash::FxHashMap; use lean_ffi::object::{ @@ -48,40 +48,36 @@ use lean_ffi::object::{ use crate::lean::LeanIxCheckError; #[cfg(feature = "test-ffi")] -use crate::ffi::lean_env::{GlobalCache, decode_name}; -use crate::ffi::lean_env::{decode_env, decode_name_array}; -use crate::ix::address::Address; -use crate::ix::compile::{ +use crate::lean_env::{GlobalCache, decode_name}; +use crate::lean_env::{decode_env, decode_name_array}; +use ix_common::address::Address; +use ix_common::env::{Name, NameData}; +use ix_compile::compile::{ CompileOptions, CompileState, compile_env_with_options, }; #[cfg(feature = "test-ffi")] -use crate::ix::decompile::decompile_env; -use crate::ix::env::{Name, NameData}; -use crate::ix::ixon::constant::ConstantInfo as IxonCI; +use ix_compile::decompile::decompile_env; #[cfg(feature = "test-ffi")] -use crate::ix::ixon::constant::MutConst as IxonMutConst; -use crate::ix::ixon::env::Env as IxonEnv; -#[cfg(feature = "test-ffi")] -use crate::ix::ixon::expr::Expr as IxonExpr; -use crate::ix::ixon::metadata::ConstantMetaInfo; -#[cfg(feature = "test-ffi")] -use crate::ix::kernel::egress::{ixon_egress, lean_egress}; -use crate::ix::kernel::env::KEnv; -use crate::ix::kernel::error::TcError; -use crate::ix::kernel::id::KId; -use crate::ix::kernel::ingress::{ +use ix_compile::kernel_egress::{ixon_egress, lean_egress}; +use ix_kernel::env::KEnv; +use ix_kernel::error::TcError; +use ix_kernel::id::KId; +use ix_kernel::ingress::{ IxonIngressLookups, build_ixon_ingress_lookups, ingress_const_shallow_into_kenv_with_lookups, ixon_ingress_owned, }; -use crate::ix::kernel::ingress::{ - anon_ctor_proj_addr, anon_defn_proj_addr, anon_indc_proj_addr, - anon_recr_proj_addr, -}; #[cfg(feature = "test-ffi")] -use crate::ix::kernel::ingress::{ixon_ingress, lean_ingress}; -use crate::ix::kernel::mode::{Anon, CheckDupLevelParams, KernelMode, Meta}; -use crate::ix::kernel::tc::TypeChecker; -use crate::ix::profile::{BlockProfile, ProfileBuilder, ProfileSink}; +use ix_kernel::ingress::{ixon_ingress, lean_ingress}; +use ix_kernel::mode::{Anon, CheckDupLevelParams, KernelMode, Meta}; +use ix_kernel::profile::{BlockProfile, ProfileBuilder, ProfileSink}; +use ix_kernel::tc::TypeChecker; +use ixon::constant::ConstantInfo as IxonCI; +#[cfg(feature = "test-ffi")] +use ixon::constant::MutConst as IxonMutConst; +use ixon::env::Env as IxonEnv; +#[cfg(feature = "test-ffi")] +use ixon::expr::Expr as IxonExpr; +use ixon::metadata::ConstantMetaInfo; unsafe extern "C" { fn lean_name_mk_string( @@ -448,7 +444,7 @@ fn poison_second_rec_rule_returns_first_minor( let rec_arc = ixon_env.get_const(&rec_addr).ok_or_else(|| { format!("{}: missing constant {}", rec_name.pretty(), rec_addr.hex()) })?; - let mut rec_constant: crate::ix::ixon::constant::Constant = + let mut rec_constant: ixon::constant::Constant = (*rec_arc).clone(); drop(rec_arc); @@ -485,7 +481,7 @@ fn poison_second_rec_rule_returns_first_minor( block_addr.hex() ) })?; - let mut block_constant: crate::ix::ixon::constant::Constant = + let mut block_constant: ixon::constant::Constant = (*block_arc).clone(); drop(block_arc); match &mut block_constant.info { @@ -533,7 +529,7 @@ fn poison_second_rec_rule_returns_first_minor( #[cfg(feature = "test-ffi")] fn poison_recursor_rule_payload( - rec: &mut crate::ix::ixon::constant::Recursor, + rec: &mut ixon::constant::Recursor, ) -> Result<(), String> { if rec.rules.len() < 2 { return Err(format!( @@ -746,7 +742,7 @@ pub extern "C" fn rs_kernel_ixon_names( /// to downstream consumers (Aiur, kernel primitive resolution). #[unsafe(no_mangle)] pub extern "C" fn rs_prim_addrs_canonical() -> LeanIOResult { - let table = crate::ix::kernel::primitive::PrimAddrs::lean_parity_table(); + let table = ix_kernel::primitive::PrimAddrs::lean_parity_table(); let arr = LeanArray::alloc(table.len()); for (i, (name, hex)) in table.iter().enumerate() { let name_obj: LeanOwned = LeanString::new(name).into(); @@ -792,7 +788,7 @@ fn build_lean_name(name: &Name) -> LeanOwned { }, NameData::Num(parent, n, _) => { let parent = build_lean_name(parent); - let part = Nat::to_lean(n); + let part = LeanNat::from_nat(n); unsafe { LeanOwned::from_raw(lean_name_mk_numeral( parent.into_raw(), @@ -1298,6 +1294,11 @@ fn resolve_kernel_check_workers_from( // The lazy ingress mechanism (in `tc.rs`) handles cross-block faults // without consulting metadata. +/// FFI-side anon work item with per-target result-slot indices. +/// +/// Wraps [`ix_kernel::anon_work::AnonWorkItem`] with the index +/// mapping the parallel runner needs to write per-target results +/// into a flat `OnceLock` vector for the FFI return ABI. #[derive(Clone, Debug)] enum AnonWorkItem { /// A standalone (non-mutual, non-projection) constant. @@ -1314,93 +1315,34 @@ enum AnonWorkItem { /// target addresses (one per result slot). Skips projection constants /// (covered by their parent block) and Muts addresses themselves /// (blocks aren't kernel KIds). +/// +/// Delegates the enumeration to +/// [`ix_kernel::anon_work::build_anon_work`] (shared with the +/// SP1/Zisk guests) and layers the FFI's per-target result-slot +/// bookkeeping on top. fn build_anon_work( env: &IxonEnv, ) -> Result<(Vec, Vec
), String> { - use crate::ix::ixon::constant::ConstantInfo as CI; - use crate::ix::ixon::constant::MutConst as MC; - use crate::ix::ixon::lazy::ConstVariantTag as Tag; + use ix_kernel::anon_work::AnonWorkItem as KItem; - let mut work: Vec = Vec::new(); + let kernel_work = ix_kernel::anon_work::build_anon_work(env)?; + let mut work: Vec = Vec::with_capacity(kernel_work.len()); let mut addrs: Vec
= Vec::new(); - - // Sort keys for deterministic ordering across runs. - let mut keys: Vec
= - env.consts.iter().map(|e| e.key().clone()).collect(); - keys.sort_unstable(); - - // Dispatch on the outer Tag4 byte via `peek_variant` — no body - // parse, no allocation. Only `Muts` blocks require a full - // materialization (to enumerate members for projection-address - // computation); the resulting `Arc` drops at the end of - // that match arm. Standalones (Defn/Recr/Axio/Quot, ~95% of the - // env) and projection skips don't even touch the body. - // - // Before this change, every constant was fully materialized here - // and (worse) pinned forever in `LazyConstant.cache`'s OnceLock. - // For mathlib that pinned ~30 GB of parsed `Arc` trees in - // the shared `Arc` before kernel checking even started. - // The cache-free `LazyConstant` policy + this peek path keep - // env-side memory bounded to "bytes (mmap'd) + per-const headers". - for addr in keys { - let lc = env.consts.get(&addr).ok_or_else(|| { - format!("build_anon_work: missing const at {}", addr.hex()) - })?; - let tag = lc.value().peek_variant().map_err(|e| { - format!("build_anon_work: peek_variant {}: {e}", addr.hex()) - })?; - match tag { - Tag::IPrj | Tag::CPrj | Tag::RPrj | Tag::DPrj => { - // Skip; covered by parent block. - }, - Tag::Defn | Tag::Recr | Tag::Axio | Tag::Quot => { + for item in kernel_work { + match item { + KItem::Standalone { addr } => { let result_idx = addrs.len(); addrs.push(addr.clone()); - work.push(AnonWorkItem::Standalone { result_idx, addr: addr.clone() }); + work.push(AnonWorkItem::Standalone { result_idx, addr }); }, - Tag::Muts => { - // Materialize once to enumerate members; the `Arc` - // drops at the end of this arm — no cache retention. - let constant = lc.value().get().map_err(|e| { - format!("build_anon_work: materialize Muts {}: {e}", addr.hex()) - })?; - let CI::Muts(members) = &constant.info else { - return Err(format!( - "build_anon_work: Tag::Muts but ConstantInfo is {:?} at {}", - constant.info.variant(), - addr.hex() - )); - }; - // Compute kernel-checkable targets deterministically. Each - // member contributes its projection address; inductive members - // contribute one CPrj per constructor. - let mut targets: Vec
= Vec::new(); - for (i, member) in members.iter().enumerate() { - let i = i as u64; - let member_addr = match member { - MC::Defn(_) => anon_defn_proj_addr(&addr, i), - MC::Indc(_) => anon_indc_proj_addr(&addr, i), - MC::Recr(_) => anon_recr_proj_addr(&addr, i), - }; - targets.push(member_addr); - if let MC::Indc(ind) = member { - for cidx in 0..ind.ctors.len() as u64 { - targets.push(anon_ctor_proj_addr(&addr, i, cidx)); - } - } - } - if targets.is_empty() { - continue; - } - let primary_addr = targets[0].clone(); - let result_idxs: Vec = - (addrs.len()..addrs.len() + targets.len()).collect(); + KItem::Block { primary, targets, .. } => { + let start = addrs.len(); + let result_idxs: Vec = (start..start + targets.len()).collect(); addrs.extend(targets); - work.push(AnonWorkItem::Block { primary_addr, result_idxs }); + work.push(AnonWorkItem::Block { primary_addr: primary, result_idxs }); }, } } - Ok((work, addrs)) } @@ -1940,7 +1882,7 @@ pub extern "C" fn rs_shard_esp( let out = out_path.to_string(); let out_opt = if out.is_empty() { None } else { Some(out.as_str()) }; let balance = (balance_pct as f64) / 100.0; - match crate::ix::shard::shard_esp( + match ix_kernel::shard::shard_esp( &esp_path.to_string(), num_shards, balance, @@ -3072,7 +3014,7 @@ pub extern "C" fn rs_kernel_roundtrip( // Build a plain Lean `Env` from decompile's DashMap for the standard // compare_envs / find_diff flow. let t5 = Instant::now(); - let mut decompiled_env = crate::ix::env::Env::default(); + let mut decompiled_env = ix_common::env::Env::default(); for entry in dstt.env.iter() { decompiled_env.insert(entry.key().clone(), entry.value().clone()); } @@ -3108,10 +3050,10 @@ pub extern "C" fn rs_kernel_roundtrip( /// manageable. #[cfg(feature = "test-ffi")] fn compare_envs( - original: &crate::ix::env::Env, - egressed: &crate::ix::env::Env, + original: &ix_common::env::Env, + egressed: &ix_common::env::Env, ) -> (Vec, usize, usize) { - use crate::ix::env::ConstantInfo as LCI; + use ix_common::env::ConstantInfo as LCI; let total = original.len(); let mut errors: Vec = Vec::new(); @@ -3181,11 +3123,11 @@ fn compare_envs( /// Returns a path-annotated description of where the mismatch is. #[cfg(feature = "test-ffi")] fn find_diff( - a: &crate::ix::env::Expr, - b: &crate::ix::env::Expr, + a: &ix_common::env::Expr, + b: &ix_common::env::Expr, path: &str, ) -> String { - use crate::ix::env::ExprData; + use ix_common::env::ExprData; if a.get_hash() == b.get_hash() { return format!("{path}: hashes match (ok)"); @@ -3281,7 +3223,7 @@ fn find_diff( let mut val_diffs = Vec::new(); for (i, ((n1, v1), (_, v2))) in kvs1.iter().zip(kvs2.iter()).enumerate() { - use crate::ix::env::hash_data_value; + use ix_common::env::hash_data_value; let mut h1 = blake3::Hasher::new(); let mut h2 = blake3::Hasher::new(); hash_data_value(v1, &mut h1); diff --git a/src/lean.rs b/crates/ffi/src/lean.rs similarity index 100% rename from src/lean.rs rename to crates/ffi/src/lean.rs diff --git a/src/ffi/lean_env.rs b/crates/ffi/src/lean_env.rs similarity index 94% rename from src/ffi/lean_env.rs rename to crates/ffi/src/lean_env.rs index 13296fa9..5230dd79 100644 --- a/src/ffi/lean_env.rs +++ b/crates/ffi/src/lean_env.rs @@ -2,7 +2,7 @@ //! //! Provides functions to walk Lean object pointers and decode them into //! the Rust `Name`, `Level`, `Expr`, and `ConstantInfo` types defined in -//! `crate::ix::env`. Used by the compilation pipeline to read the Lean +//! `ix_common::env`. Used by the compilation pipeline to read the Lean //! environment before transforming it to Ixon format. //! //! Uses a two-level cache (`GlobalCache` + `LocalCache`) to avoid redundant @@ -17,11 +17,12 @@ use rayon::prelude::*; use rustc_hash::FxHashMap; -use crate::ix::compile::{CompileOptions, compile_env_with_options}; -use crate::ix::decompile::{check_decompile, decompile_env}; +use ix_compile::compile::{CompileOptions, compile_env_with_options}; +use ix_compile::decompile::{check_decompile, decompile_env}; use std::sync::Arc; use lean_ffi::nat::Nat; +use lean_ffi::object::LeanNat; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanList, LeanRef, LeanShared, }; @@ -35,7 +36,7 @@ use crate::lean::{ LeanIxSyntaxPreresolved, LeanIxTheoremVal, }; -use crate::ix::env::{ +use ix_common::env::{ AxiomVal, BinderInfo, ConstantInfo, ConstantVal, ConstructorVal, DataValue, DefinitionSafety, DefinitionVal, Env, Expr, InductiveVal, Int, Level, Literal, Name, OpaqueVal, QuotKind, QuotVal, RecursorRule, RecursorVal, @@ -55,7 +56,7 @@ const PARALLEL_THRESHOLD: usize = 100; /// generated recursor is intentionally canonical rather than source-identical. fn primary_addresses_collapse( all: &[Name], - stt: &crate::ix::compile::CompileState, + stt: &ix_compile::compile::CompileState, ) -> bool { let mut seen = rustc_hash::FxHashSet::default(); for name in all { @@ -72,12 +73,12 @@ fn primary_addresses_collapse( fn build_aux_perm_ctx( all: &[Name], env: &Env, - stt: &crate::ix::compile::CompileState, + stt: &ix_compile::compile::CompileState, perm: &[usize], -) -> Option { - use crate::ix::compile::aux_gen; - use crate::ix::congruence::perm::{PermCtx, RecHeadInfo, RecHeadKind}; - use crate::ix::env::{ConstantInfo as LeanCI, ExprData}; +) -> Option { + use ix_common::env::{ConstantInfo as LeanCI, ExprData}; + use ix_compile::compile::aux_gen; + use ix_compile::congruence::perm::{PermCtx, RecHeadInfo, RecHeadKind}; let first = all.first()?; let n_params = match env.get(first) { @@ -162,7 +163,7 @@ fn build_aux_perm_ctx( ); } - let mut const_addr: FxHashMap = + let mut const_addr: FxHashMap = FxHashMap::default(); let mut add_addr = |name: &Name| { if let Some(addr) = stt.resolve_addr(name) { @@ -194,8 +195,8 @@ fn build_aux_perm_ctx( fn collect_const_addrs( e: &Expr, - stt: &crate::ix::compile::CompileState, - out: &mut FxHashMap, + stt: &ix_compile::compile::CompileState, + out: &mut FxHashMap, ) { match e.as_data() { ExprData::Const(n, _, _) => { @@ -261,13 +262,13 @@ fn build_aux_perm_ctx( fn build_collapse_const_map( all: &[Name], env: &Env, - stt: &crate::ix::compile::CompileState, + stt: &ix_compile::compile::CompileState, ) -> FxHashMap { - use crate::ix::env::ConstantInfo as LeanCI; + use ix_common::env::ConstantInfo as LeanCI; let mut map: FxHashMap = FxHashMap::default(); // Group primary members by canonical address; the first member with a // given address is the representative. - let mut rep_by_addr: FxHashMap = + let mut rep_by_addr: FxHashMap = FxHashMap::default(); for member in all { let Some(addr) = stt.resolve_addr(member) else { @@ -323,21 +324,21 @@ fn build_collapse_const_map( #[derive(Clone)] struct AuxCompareEntry { generated: ConstantInfo, - ctx: Option, + ctx: Option, } fn aux_patch_to_lean_ci( - patch: &crate::ix::compile::aux_gen::PatchedConstant, -) -> Option { - use crate::ix::env::{ + patch: &ix_compile::compile::aux_gen::PatchedConstant, +) -> ConstantInfo { + use ix_common::env::{ ConstantInfo as LeanCI, ConstantVal as LeanCV, DefinitionVal, InductiveVal, }; - Some(match patch { - crate::ix::compile::aux_gen::PatchedConstant::Rec(r) => { + match patch { + ix_compile::compile::aux_gen::PatchedConstant::Rec(r) => { LeanCI::RecInfo(r.clone()) }, - crate::ix::compile::aux_gen::PatchedConstant::CasesOn(d) - | crate::ix::compile::aux_gen::PatchedConstant::RecOn(d) => { + ix_compile::compile::aux_gen::PatchedConstant::CasesOn(d) + | ix_compile::compile::aux_gen::PatchedConstant::RecOn(d) => { LeanCI::DefnInfo(DefinitionVal { cnst: LeanCV { name: d.name.clone(), @@ -350,7 +351,7 @@ fn aux_patch_to_lean_ci( all: vec![], }) }, - crate::ix::compile::aux_gen::PatchedConstant::BelowDef(d) => { + ix_compile::compile::aux_gen::PatchedConstant::BelowDef(d) => { LeanCI::DefnInfo(DefinitionVal { cnst: LeanCV { name: d.name.clone(), @@ -363,7 +364,7 @@ fn aux_patch_to_lean_ci( all: vec![], }) }, - crate::ix::compile::aux_gen::PatchedConstant::BRecOn(d) => { + ix_compile::compile::aux_gen::PatchedConstant::BRecOn(d) => { LeanCI::DefnInfo(DefinitionVal { cnst: LeanCV { name: d.name.clone(), @@ -376,7 +377,7 @@ fn aux_patch_to_lean_ci( all: vec![], }) }, - crate::ix::compile::aux_gen::PatchedConstant::BelowIndc(bi) => { + ix_compile::compile::aux_gen::PatchedConstant::BelowIndc(bi) => { LeanCI::InductInfo(InductiveVal { cnst: LeanCV { name: bi.name.clone(), @@ -393,7 +394,7 @@ fn aux_patch_to_lean_ci( is_reflexive: bi.is_reflexive, }) }, - }) + } } fn aux_congruence_result( @@ -402,8 +403,8 @@ fn aux_congruence_result( original: &ConstantInfo, entry: Option<&AuxCompareEntry>, ) -> Result<(), String> { - use crate::ix::congruence::const_alpha_eq; - use crate::ix::congruence::perm::const_alpha_eq_with_perm; + use ix_compile::congruence::const_alpha_eq; + use ix_compile::congruence::perm::const_alpha_eq_with_perm; if let Ok(()) = const_alpha_eq(decompiled, original) { return Ok(()); } @@ -478,11 +479,11 @@ fn aux_congruence_result( fn build_aux_compare_contexts( env: &Arc, - stt: &crate::ix::compile::CompileState, + stt: &ix_compile::compile::CompileState, ) -> FxHashMap { - use crate::ix::compile::KernelCtx; - use crate::ix::compile::aux_gen::{self, expr_utils}; - use crate::ix::env::ConstantInfo as LeanCI; + use ix_common::env::ConstantInfo as LeanCI; + use ix_compile::compile::KernelCtx; + use ix_compile::compile::aux_gen::{self, expr_utils}; use rustc_hash::FxHashSet; let mut by_name = FxHashMap::default(); @@ -523,12 +524,11 @@ fn build_aux_compare_contexts( None }; for (patch_name, patch) in aux_out.patches.iter() { - if let Some(generated) = aux_patch_to_lean_ci(patch) { - by_name.insert( - patch_name.clone(), - AuxCompareEntry { generated, ctx: ctx.clone() }, - ); - } + let generated = aux_patch_to_lean_ci(patch); + by_name.insert( + patch_name.clone(), + AuxCompareEntry { generated, ctx: ctx.clone() }, + ); } } by_name @@ -610,7 +610,7 @@ pub fn decode_name(obj: LeanBorrowed<'_>, global: &GlobalCache) -> Name { let pos = n.get_obj(1); match n.as_ctor().tag() { 1 => Name::str(pre, pos.as_string().to_string()), - 2 => Name::num(pre, Nat::from_obj(&pos)), + 2 => Name::num(pre, LeanNat::to_nat(&pos)), tag => unreachable!("Invalid Lean.Name tag: {tag}"), } }; @@ -668,8 +668,8 @@ fn decode_level(obj: LeanBorrowed<'_>, cache: &mut Cache<'_>) -> Level { fn decode_substring(obj: LeanBorrowed<'_>) -> Substring { let s = LeanIxSubstring::from_ctor(obj.as_ctor()); let str = s.get_obj(0).as_string().to_string(); - let start_pos = Nat::from_obj(&s.get_obj(1)); - let stop_pos = Nat::from_obj(&s.get_obj(2)); + let start_pos = LeanNat::to_nat(&s.get_obj(1)); + let stop_pos = LeanNat::to_nat(&s.get_obj(2)); Substring { str, start_pos, stop_pos } } @@ -681,14 +681,14 @@ fn decode_source_info(obj: LeanBorrowed<'_>) -> SourceInfo { match si.as_ctor().tag() { 0 => { let leading = decode_substring(si.get_obj(0)); - let pos = Nat::from_obj(&si.get_obj(1)); + let pos = LeanNat::to_nat(&si.get_obj(1)); let trailing = decode_substring(si.get_obj(2)); - let end_pos = Nat::from_obj(&si.get_obj(3)); + let end_pos = LeanNat::to_nat(&si.get_obj(3)); SourceInfo::Original(leading, pos, trailing, end_pos) }, 1 => { - let pos = Nat::from_obj(&si.get_obj(0)); - let end_pos = Nat::from_obj(&si.get_obj(1)); + let pos = LeanNat::to_nat(&si.get_obj(0)); + let end_pos = LeanNat::to_nat(&si.get_obj(1)); let canonical = si.get_num_8(0) != 0; SourceInfo::Synthetic(pos, end_pos, canonical) }, @@ -768,10 +768,10 @@ fn decode_name_data_value( 0 => DataValue::OfString(dv.get_obj(0).as_string().to_string()), 1 => DataValue::OfBool(dv.get_num_8(0) != 0), 2 => DataValue::OfName(decode_name(dv.get_obj(0), cache.global)), - 3 => DataValue::OfNat(Nat::from_obj(&dv.get_obj(0))), + 3 => DataValue::OfNat(LeanNat::to_nat(&dv.get_obj(0))), 4 => { let i = LeanIxInt::from_ctor(dv.get_obj(0).as_ctor()); - let nat = Nat::from_obj(&i.get_obj(0)); + let nat = LeanNat::to_nat(&i.get_obj(0)); let int = match i.as_ctor().tag() { 0 => Int::OfNat(nat), 1 => Int::NegSucc(nat), @@ -799,7 +799,7 @@ pub fn decode_expr(obj: LeanBorrowed<'_>, cache: &mut Cache<'_>) -> Expr { _ => unreachable!("Invalid Lean.BinderInfo tag: {b}"), }; let expr = match e.as_ctor().tag() { - 0 => Expr::bvar(Nat::from_obj(&e.get_obj(0))), + 0 => Expr::bvar(LeanNat::to_nat(&e.get_obj(0))), 1 => Expr::fvar(decode_name(e.get_obj(0), cache.global)), 2 => Expr::mvar(decode_name(e.get_obj(0), cache.global)), 3 => Expr::sort(decode_level(e.get_obj(0), cache)), @@ -842,7 +842,7 @@ pub fn decode_expr(obj: LeanBorrowed<'_>, cache: &mut Cache<'_>) -> Expr { let lit = LeanIxLiteral::from_ctor(e.get_obj(0).as_ctor()); let inner = lit.get_obj(0); match lit.as_ctor().tag() { - 0 => Expr::lit(Literal::NatVal(Nat::from_obj(&inner))), + 0 => Expr::lit(Literal::NatVal(LeanNat::to_nat(&inner))), 1 => Expr::lit(Literal::StrVal(inner.as_string().to_string())), tag => unreachable!("Invalid Lean.Literal tag: {tag}"), } @@ -857,7 +857,7 @@ pub fn decode_expr(obj: LeanBorrowed<'_>, cache: &mut Cache<'_>) -> Expr { }, 11 => { let typ_name = decode_name(e.get_obj(0), cache.global); - let idx = Nat::from_obj(&e.get_obj(1)); + let idx = LeanNat::to_nat(&e.get_obj(1)); let struct_expr = decode_expr(e.get_obj(2), cache); Expr::proj(typ_name, idx, struct_expr) }, @@ -873,7 +873,7 @@ fn decode_recursor_rule( ) -> RecursorRule { let r = LeanIxRecursorRule::from_ctor(obj.as_ctor()); let ctor_name = decode_name(r.get_obj(0), cache.global); - let n_fields = Nat::from_obj(&r.get_obj(1)); + let n_fields = LeanNat::to_nat(&r.get_obj(1)); let rhs = decode_expr(r.get_obj(2), cache); RecursorRule { ctor: ctor_name, n_fields, rhs } } @@ -980,8 +980,8 @@ pub fn decode_constant_info( 5 => { let inner = LeanIxInductiveVal::from_ctor(inner_obj.as_ctor()); let constant_val = decode_constant_val(inner.get_obj(0), cache); - let num_params = Nat::from_obj(&inner.get_obj(1)); - let num_indices = Nat::from_obj(&inner.get_obj(2)); + let num_params = LeanNat::to_nat(&inner.get_obj(1)); + let num_indices = LeanNat::to_nat(&inner.get_obj(2)); let all: Vec<_> = collect_list_borrowed(inner.get_obj(3).as_list()) .into_iter() .map(|o| decode_name(o, cache.global)) @@ -990,7 +990,7 @@ pub fn decode_constant_info( .into_iter() .map(|o| decode_name(o, cache.global)) .collect(); - let num_nested = Nat::from_obj(&inner.get_obj(5)); + let num_nested = LeanNat::to_nat(&inner.get_obj(5)); let is_rec = inner.get_num_8(0) != 0; let is_unsafe = inner.get_num_8(1) != 0; let is_reflexive = inner.get_num_8(2) != 0; @@ -1010,9 +1010,9 @@ pub fn decode_constant_info( let inner = LeanIxConstructorVal::from_ctor(inner_obj.as_ctor()); let constant_val = decode_constant_val(inner.get_obj(0), cache); let induct = decode_name(inner.get_obj(1), cache.global); - let cidx = Nat::from_obj(&inner.get_obj(2)); - let num_params = Nat::from_obj(&inner.get_obj(3)); - let num_fields = Nat::from_obj(&inner.get_obj(4)); + let cidx = LeanNat::to_nat(&inner.get_obj(2)); + let num_params = LeanNat::to_nat(&inner.get_obj(3)); + let num_fields = LeanNat::to_nat(&inner.get_obj(4)); let is_unsafe = inner.get_num_8(0) != 0; ConstantInfo::CtorInfo(ConstructorVal { cnst: constant_val, @@ -1030,10 +1030,10 @@ pub fn decode_constant_info( .into_iter() .map(|o| decode_name(o, cache.global)) .collect(); - let num_params = Nat::from_obj(&inner.get_obj(2)); - let num_indices = Nat::from_obj(&inner.get_obj(3)); - let num_motives = Nat::from_obj(&inner.get_obj(4)); - let num_minors = Nat::from_obj(&inner.get_obj(5)); + let num_params = LeanNat::to_nat(&inner.get_obj(2)); + let num_indices = LeanNat::to_nat(&inner.get_obj(3)); + let num_motives = LeanNat::to_nat(&inner.get_obj(4)); + let num_minors = LeanNat::to_nat(&inner.get_obj(5)); let rules: Vec<_> = collect_list_borrowed(inner.get_obj(6).as_list()) .into_iter() .map(|o| decode_recursor_rule(o, cache)) @@ -1117,11 +1117,11 @@ extern "C" fn rs_tmp_decode_const_map( obj: LeanList>, ) -> usize { // Enable hash-consed size tracking for debugging - crate::ix::compile::TRACK_HASH_CONSED_SIZE + ix_compile::compile::TRACK_HASH_CONSED_SIZE .store(true, std::sync::atomic::Ordering::Relaxed); // Enable verbose sharing analysis for debugging pathological blocks - crate::ix::compile::ANALYZE_SHARING + ix_compile::compile::ANALYZE_SHARING .store(false, std::sync::atomic::Ordering::Relaxed); let env = decode_env(obj); @@ -1150,12 +1150,12 @@ extern "C" fn rs_tmp_decode_const_map( // Phase 1b: Aux_gen congruence (full env) eprintln!("[rust-compile] Phase 1b: Checking aux_gen congruence..."); { - use crate::ix::compile::aux_gen::{self, PatchedConstant, expr_utils}; - use crate::ix::congruence::const_alpha_eq; - use crate::ix::env::{ + use ix_common::env::{ ConstantInfo as LeanCI, ConstantVal as LeanCV, DefinitionSafety, DefinitionVal, InductiveVal, ReducibilityHints, }; + use ix_compile::compile::aux_gen::{self, PatchedConstant, expr_utils}; + use ix_compile::congruence::const_alpha_eq; use rustc_hash::{FxHashMap, FxHashSet}; // Build per-block PermCtx for the permutation-aware comparator. @@ -1165,11 +1165,11 @@ extern "C" fn rs_tmp_decode_const_map( fn build_perm_ctx_1b( all: &[Name], env: &Env, - stt: &crate::ix::compile::CompileState, + stt: &ix_compile::compile::CompileState, perm: &[usize], - ) -> Option { - use crate::ix::congruence::perm::{PermCtx, RecHeadInfo, RecHeadKind}; - use crate::ix::env::{ConstantInfo as LeanCI, ExprData}; + ) -> Option { + use ix_common::env::{ConstantInfo as LeanCI, ExprData}; + use ix_compile::congruence::perm::{PermCtx, RecHeadInfo, RecHeadKind}; let first = all.first()?; let n_params = match env.get(first) { @@ -1257,7 +1257,7 @@ extern "C" fn rs_tmp_decode_const_map( ); } - let mut const_addr: FxHashMap = + let mut const_addr: FxHashMap = FxHashMap::default(); let mut add_addr = |name: &Name| { if let Some(addr) = stt.resolve_addr(name) { @@ -1290,8 +1290,8 @@ extern "C" fn rs_tmp_decode_const_map( } fn collect_const_addrs( e: &Expr, - stt: &crate::ix::compile::CompileState, - out: &mut FxHashMap, + stt: &ix_compile::compile::CompileState, + out: &mut FxHashMap, ) { match e.as_data() { ExprData::Const(n, _, _) => { @@ -1377,7 +1377,7 @@ extern "C" fn rs_tmp_decode_const_map( continue; } - let mut local_kctx = crate::ix::compile::KernelCtx::new(); + let mut local_kctx = ix_compile::compile::KernelCtx::new(); expr_utils::ensure_prelude_in_kenv_of(&stt, &mut local_kctx); let orig_aux_out = match aux_gen::generate_aux_patches( &original_classes, @@ -1405,7 +1405,7 @@ extern "C" fn rs_tmp_decode_const_map( // `rs_compile_validate_aux`) for the full builder; the // `#[cfg(feature = "test-ffi")]` Phase 1b path here uses a // local copy with the same logic. - let perm_ctx_1b: Option = + let perm_ctx_1b: Option = if let Some(perm) = &orig_aux_out.perm && !perm.is_empty() { @@ -1475,7 +1475,7 @@ extern "C" fn rs_tmp_decode_const_map( }; let orig_ci: &LeanCI = orig_ci_ref; let eq_result = match &perm_ctx_1b { - Some(ctx) => crate::ix::congruence::perm::const_alpha_eq_with_perm( + Some(ctx) => ix_compile::congruence::perm::const_alpha_eq_with_perm( &gen_ci, orig_ci, ctx, ), None => const_alpha_eq(&gen_ci, orig_ci), @@ -1598,9 +1598,9 @@ extern "C" fn rs_tmp_decode_const_map( eprintln!("[rust-compile] Phase 6: Deserializing and re-decompiling..."); let t4 = std::time::Instant::now(); let mut buf: &[u8] = &serialized; - match crate::ix::ixon::env::Env::get(&mut buf) { + match ixon::env::Env::get(&mut buf) { Ok(fresh_env) => { - let fresh_stt = crate::ix::compile::CompileState { + let fresh_stt = ix_compile::compile::CompileState { env: fresh_env, ..Default::default() }; @@ -1690,7 +1690,7 @@ impl PhaseResult { extern "C" fn rs_compile_validate_aux( obj: LeanList>, ) -> usize { - use crate::ix::congruence::const_alpha_eq; + use ix_compile::congruence::const_alpha_eq; use rustc_hash::FxHashSet; let t_total = std::time::Instant::now(); @@ -1796,10 +1796,10 @@ extern "C" fn rs_compile_validate_aux( let mut p2 = PhaseResult::new("2. Aux_gen congruence"); println!("{VALIDATE_PREFIX} phase 2: checking aux_gen congruence..."); { - use crate::ix::compile::aux_gen::{self, PatchedConstant, expr_utils}; - use crate::ix::compile::{KernelCtx, mk_indc}; - use crate::ix::env::ConstantInfo as LeanCI; - use crate::ix::mutual::MutConst; + use ix_common::env::ConstantInfo as LeanCI; + use ix_compile::compile::aux_gen::{self, PatchedConstant, expr_utils}; + use ix_compile::compile::{KernelCtx, mk_indc}; + use ix_compile::mutual::MutConst; // Ephemeral kernel context for original-structure congruence testing. // Shared across all blocks (accumulates inductives incrementally). @@ -1867,7 +1867,7 @@ extern "C" fn rs_compile_validate_aux( // introducing races (even though individual DashMap inserts are safe, // a reader may observe a partially-ingressed kctx and fail). { - use crate::ix::graph::get_constant_info_references; + use ix_compile::graph::get_constant_info_references; // Step A (serial): enumerate the transitive-closure of names to // ingress. BFS walking the env hashmap is cheap — the per-node cost // is a lookup and a ref-walk, dwarfed by Step B's actual ingress. @@ -1913,18 +1913,18 @@ extern "C" fn rs_compile_validate_aux( // Build a `PermCtx` for the block: the congruence comparator uses // it to walk gen vs orig in lockstep with permutation awareness. - // See `crate::ix::congruence::perm` for details. + // See `ix_compile::congruence::perm` for details. // // `n_primary = all.len()` because Phase 2 uses singleton classes // (one class per original, no alpha-collapse at the primary level). fn build_perm_ctx( all: &[Name], env: &Env, - stt: &crate::ix::compile::CompileState, + stt: &ix_compile::compile::CompileState, perm: &[usize], - ) -> Option { - use crate::ix::congruence::perm::{PermCtx, RecHeadInfo}; - use crate::ix::env::ConstantInfo as LeanCI; + ) -> Option { + use ix_common::env::ConstantInfo as LeanCI; + use ix_compile::congruence::perm::{PermCtx, RecHeadInfo}; use rustc_hash::FxHashMap; let first = all.first()?; @@ -1968,7 +1968,7 @@ extern "C" fn rs_compile_validate_aux( // - Aux `.below_N` (kind = Below) — `{first}.below_{N}` // - Primary `.brecOn`/.go/.eq (kind = BRecOn) // - Aux `.brecOn_N`/.go/.eq (kind = BRecOn) - use crate::ix::congruence::perm::RecHeadKind; + use ix_compile::congruence::perm::RecHeadKind; let n_motives = n_primary + source_aux_ctor_counts.len(); let n_minors: usize = primary_ctor_counts.iter().sum::() + source_aux_ctor_counts.iter().sum::(); @@ -2049,7 +2049,7 @@ extern "C" fn rs_compile_validate_aux( // operate on collapsed blocks pick up the rewrites automatically. // (Built below at the PermCtx construction site so `env`/`stt` // borrows don't conflict with the const_addr-collecting closure.) - let mut const_addr: FxHashMap = + let mut const_addr: FxHashMap = FxHashMap::default(); let mut add_addr = |name: &Name| { if let Some(addr) = stt.resolve_addr(name) { @@ -2084,10 +2084,10 @@ extern "C" fn rs_compile_validate_aux( } fn collect_const_addrs( e: &Expr, - stt: &crate::ix::compile::CompileState, - out: &mut FxHashMap, + stt: &ix_compile::compile::CompileState, + out: &mut FxHashMap, ) { - use crate::ix::env::ExprData; + use ix_common::env::ExprData; match e.as_data() { ExprData::Const(n, _, _) => { if let Some(addr) = stt.resolve_addr(n) { @@ -2145,12 +2145,12 @@ extern "C" fn rs_compile_validate_aux( } // Helper to wrap a patch as a Lean `ConstantInfo` for alpha-eq. - fn patch_to_lean_ci(patch: &PatchedConstant) -> Option { - use crate::ix::env::{ + fn patch_to_lean_ci(patch: &PatchedConstant) -> ConstantInfo { + use ix_common::env::{ ConstantInfo as LeanCI, ConstantVal as LeanCV, DefinitionSafety, DefinitionVal, InductiveVal, ReducibilityHints, }; - Some(match patch { + match patch { PatchedConstant::Rec(r) => LeanCI::RecInfo(r.clone()), PatchedConstant::CasesOn(d) | PatchedConstant::RecOn(d) => { LeanCI::DefnInfo(DefinitionVal { @@ -2202,7 +2202,7 @@ extern "C" fn rs_compile_validate_aux( is_unsafe: false, is_reflexive: bi.is_reflexive, }), - }) + } } // Diagnostic dump printed per-thread on alpha-eq failure. Writes go @@ -2215,7 +2215,7 @@ extern "C" fn rs_compile_validate_aux( orig_ci: &ConstantInfo, err: &str, ) { - use crate::ix::env::{Expr, ExprData as ED}; + use ix_common::env::{Expr, ExprData as ED}; fn extract_sort(e: &Expr, depth: usize) -> String { match e.as_data() { @@ -2268,7 +2268,7 @@ extern "C" fn rs_compile_validate_aux( // Build a PermCtx for this block once. When the block has no // nested auxes (`perm == None` or empty), we pass `None` and // fall through to plain `const_alpha_eq`. - let perm_ctx: Option = + let perm_ctx: Option = if let Some(p) = &orig_aux_out.perm && !p.is_empty() { @@ -2282,16 +2282,18 @@ extern "C" fn rs_compile_validate_aux( let mut result = BlockResult::default(); let mut dumped = 0usize; for (patch_name, patch) in orig_patches.iter() { - let Some(gen_ci) = patch_to_lean_ci(patch) else { continue }; + let gen_ci = patch_to_lean_ci(patch); let Some(orig_ci_ref) = env.get(patch_name) else { continue; // Synthetic name — no Lean original. }; let orig_ci: &LeanCI = orig_ci_ref; let eq_result = match &perm_ctx { - Some(ctx) => crate::ix::congruence::perm::const_alpha_eq_with_perm( - &gen_ci, orig_ci, ctx, - ), + Some(ctx) => { + ix_compile::congruence::perm::const_alpha_eq_with_perm( + &gen_ci, orig_ci, ctx, + ) + }, None => const_alpha_eq(&gen_ci, orig_ci), }; @@ -2333,7 +2335,7 @@ extern "C" fn rs_compile_validate_aux( // Precompute canonical addresses: any orig_addr that matches another Named // entry's canonical addr is in consts legitimately (not an ephemeral leak). // The gather itself parallelizes cleanly over the DashMap. - let canonical_addrs: FxHashSet = + let canonical_addrs: FxHashSet = stt.env.named.par_iter().map(|e| e.value().addr.clone()).collect(); // Parallel scan over named DashMap. Each check is read-only against @@ -2463,17 +2465,17 @@ extern "C" fn rs_compile_validate_aux( } fn describe_addr( - stt: &crate::ix::compile::CompileState, - addr: &crate::ix::address::Address, + stt: &ix_compile::compile::CompileState, + addr: &ix_common::address::Address, ) -> String { match stt.env.get_const(addr).map(|c| c.info.clone()) { - Some(crate::ix::ixon::constant::ConstantInfo::RPrj(p)) => { + Some(ixon::constant::ConstantInfo::RPrj(p)) => { format!("RPrj(idx={}, block={:.12})", p.idx, p.block.hex()) }, - Some(crate::ix::ixon::constant::ConstantInfo::IPrj(p)) => { + Some(ixon::constant::ConstantInfo::IPrj(p)) => { format!("IPrj(idx={}, block={:.12})", p.idx, p.block.hex()) }, - Some(crate::ix::ixon::constant::ConstantInfo::CPrj(p)) => { + Some(ixon::constant::ConstantInfo::CPrj(p)) => { format!( "CPrj(idx={}, cidx={}, block={:.12})", p.idx, @@ -2487,14 +2489,14 @@ extern "C" fn rs_compile_validate_aux( } fn describe_rprj_block( - stt: &crate::ix::compile::CompileState, - addr: &crate::ix::address::Address, + stt: &ix_compile::compile::CompileState, + addr: &ix_common::address::Address, ) -> Option { fn expand_shares_expr( - expr: &Arc, - sharing: &[Arc], - ) -> Arc { - use crate::ix::ixon::expr::Expr; + expr: &Arc, + sharing: &[Arc], + ) -> Arc { + use ixon::expr::Expr; match expr.as_ref() { Expr::Share(idx) => sharing.get(*idx as usize).map_or_else( || expr.clone(), @@ -2528,10 +2530,10 @@ extern "C" fn rs_compile_validate_aux( } fn expand_shares_member( - member: &crate::ix::ixon::constant::MutConst, - sharing: &[Arc], - ) -> crate::ix::ixon::constant::MutConst { - use crate::ix::ixon::constant::{MutConst, RecursorRule}; + member: &ixon::constant::MutConst, + sharing: &[Arc], + ) -> ixon::constant::MutConst { + use ixon::constant::{MutConst, RecursorRule}; match member { MutConst::Defn(def) => { let mut def = def.clone(); @@ -2563,18 +2565,18 @@ extern "C" fn rs_compile_validate_aux( } } - fn expr_hash_prefix(expr: &Arc) -> String { + fn expr_hash_prefix(expr: &Arc) -> String { let mut buf = Vec::new(); - crate::ix::ixon::serialize::put_expr(expr, &mut buf); - let h = crate::ix::address::Address::hash(&buf); + ixon::serialize::put_expr(expr, &mut buf); + let h = ix_common::address::Address::hash(&buf); format!("{}:{}", buf.len(), &h.hex()[..12]) } fn member_parts_summary( - member: &crate::ix::ixon::constant::MutConst, - sharing: &[Arc], + member: &ixon::constant::MutConst, + sharing: &[Arc], ) -> String { - use crate::ix::ixon::constant::MutConst; + use ixon::constant::MutConst; let expanded = expand_shares_member(member, sharing); match expanded { MutConst::Defn(def) => { @@ -2598,12 +2600,12 @@ extern "C" fn rs_compile_validate_aux( } let proj = match stt.env.get_const(addr).map(|c| c.info.clone()) { - Some(crate::ix::ixon::constant::ConstantInfo::RPrj(p)) => p, + Some(ixon::constant::ConstantInfo::RPrj(p)) => p, _ => return None, }; let block = stt.env.get_const(&proj.block)?; let member_count_for_names = match &block.info { - crate::ix::ixon::constant::ConstantInfo::Muts(ms) => ms.len(), + ixon::constant::ConstantInfo::Muts(ms) => ms.len(), _ => 0, }; let proj_names: Vec = (0..member_count_for_names) @@ -2615,17 +2617,17 @@ extern "C" fn rs_compile_validate_aux( .chain(stt.name_to_addr.iter()) .filter_map(|entry| { match stt.env.get_const(entry.value()).map(|c| c.info.clone()) { - Some(crate::ix::ixon::constant::ConstantInfo::RPrj(p)) + Some(ixon::constant::ConstantInfo::RPrj(p)) if p.block == proj.block && p.idx == idx => { Some(entry.key().pretty()) }, - Some(crate::ix::ixon::constant::ConstantInfo::IPrj(p)) + Some(ixon::constant::ConstantInfo::IPrj(p)) if p.block == proj.block && p.idx == idx => { Some(entry.key().pretty()) }, - Some(crate::ix::ixon::constant::ConstantInfo::DPrj(p)) + Some(ixon::constant::ConstantInfo::DPrj(p)) if p.block == proj.block && p.idx == idx => { Some(entry.key().pretty()) @@ -2659,22 +2661,22 @@ extern "C" fn rs_compile_validate_aux( }) .collect(); let (members, per_member_hashes) = match &block.info { - crate::ix::ixon::constant::ConstantInfo::Muts(ms) => { + ixon::constant::ConstantInfo::Muts(ms) => { let per: Vec = ms .iter() .map(|m| { // Compute a per-member byte hash for quick diffing. let mut buf = Vec::new(); m.put(&mut buf); - let h = crate::ix::address::Address::hash(&buf); + let h = ix_common::address::Address::hash(&buf); let expanded = expand_shares_member(m, &block.sharing); let mut expanded_buf = Vec::new(); expanded.put(&mut expanded_buf); - let expanded_h = crate::ix::address::Address::hash(&expanded_buf); + let expanded_h = ix_common::address::Address::hash(&expanded_buf); let tag = match m { - crate::ix::ixon::constant::MutConst::Defn(_) => "Defn", - crate::ix::ixon::constant::MutConst::Indc(_) => "Indc", - crate::ix::ixon::constant::MutConst::Recr(_) => "Recr", + ixon::constant::MutConst::Defn(_) => "Defn", + ixon::constant::MutConst::Indc(_) => "Indc", + ixon::constant::MutConst::Recr(_) => "Recr", }; let parts = member_parts_summary(m, &block.sharing); format!( @@ -3563,7 +3565,7 @@ extern "C" fn rs_compile_validate_aux( // ends before we drop it. let fresh_env = { let mut buf: &[u8] = &serialized; - match crate::ix::ixon::env::Env::get(&mut buf) { + match ixon::env::Env::get(&mut buf) { Ok(fe) => Some(fe), Err(e) => { p7.record_fail(format!("deserialize FAILED: {e}")); @@ -3576,7 +3578,7 @@ extern "C" fn rs_compile_validate_aux( match fresh_env { Some(fresh_env) => { - let fresh_stt = crate::ix::compile::CompileState { + let fresh_stt = ix_compile::compile::CompileState { env: fresh_env, ..Default::default() }; @@ -3672,7 +3674,7 @@ extern "C" fn rs_compile_validate_aux( (None, None) => true, _ => false, }; - let aux_eq_result = if crate::ix::decompile::is_aux_gen_suffix(name) + let aux_eq_result = if ix_compile::decompile::is_aux_gen_suffix(name) && !(type_ok && val_ok) { Some(aux_congruence_result( @@ -3738,8 +3740,8 @@ extern "C" fn rs_compile_validate_aux( // ══════════════════════════════════════════════════════════════════════ let mut p8 = PhaseResult::new("8. Nested detection"); { - use crate::ix::compile::aux_gen::nested::build_compile_flat_block; - use crate::ix::env::ConstantInfo; + use ix_common::env::ConstantInfo; + use ix_compile::compile::aux_gen::nested::build_compile_flat_block; /// Build a dotted Lean name from a dot-separated string. /// Numeric components (e.g. the `0` in `_private.Foo.0.Bar`) are @@ -3880,7 +3882,8 @@ impl ConstSizeBreakdown { #[cfg(feature = "test-ffi")] /// Analyze the serialized size of a constant and its transitive dependencies. -fn analyze_const_size(stt: &crate::ix::compile::CompileState, name_str: &str) { +fn analyze_const_size(stt: &ix_compile::compile::CompileState, name_str: &str) { + // Build a global name index for metadata serialization let name_index = build_name_index(stt); @@ -4013,10 +4016,10 @@ fn analyze_const_size(stt: &crate::ix::compile::CompileState, name_str: &str) { /// Build a name index for metadata serialization. #[cfg(feature = "test-ffi")] fn build_name_index( - stt: &crate::ix::compile::CompileState, -) -> crate::ix::ixon::metadata::NameIndex { - use crate::ix::address::Address; - use crate::ix::ixon::metadata::NameIndex; + stt: &ix_compile::compile::CompileState, +) -> ixon::metadata::NameIndex { + use ix_common::address::Address; + use ixon::metadata::NameIndex; let mut idx = NameIndex::new(); let mut counter: u64 = 0; @@ -4037,10 +4040,10 @@ fn build_name_index( /// Compute size breakdown for a constant (alpha-invariant vs metadata). #[cfg(feature = "test-ffi")] fn compute_const_size_breakdown( - constant: &crate::ix::ixon::constant::Constant, + constant: &ixon::constant::Constant, name: &Name, - stt: &crate::ix::compile::CompileState, - name_index: &crate::ix::ixon::metadata::NameIndex, + stt: &ix_compile::compile::CompileState, + name_index: &ixon::metadata::NameIndex, ) -> ConstSizeBreakdown { // Alpha-invariant size let alpha_size = serialized_const_size(constant); @@ -4058,8 +4061,8 @@ fn compute_const_size_breakdown( /// Compute the serialized size of constant metadata. #[cfg(feature = "test-ffi")] fn serialized_meta_size( - meta: &crate::ix::ixon::metadata::ConstantMeta, - name_index: &crate::ix::ixon::metadata::NameIndex, + meta: &ixon::metadata::ConstantMeta, + name_index: &ixon::metadata::NameIndex, ) -> usize { let mut buf = Vec::new(); meta @@ -4088,9 +4091,7 @@ pub fn parse_name(s: &str) -> Name { /// Compute the serialized size of a constant. #[cfg(feature = "test-ffi")] -fn serialized_const_size( - constant: &crate::ix::ixon::constant::Constant, -) -> usize { +fn serialized_const_size(constant: &ixon::constant::Constant) -> usize { let mut buf = Vec::new(); constant.put(&mut buf); buf.len() @@ -4098,11 +4099,11 @@ fn serialized_const_size( /// Analyze block size statistics: hash-consing vs serialization. #[cfg(feature = "test-ffi")] -fn analyze_block_size_stats(stt: &crate::ix::compile::CompileState) { - use crate::ix::compile::BlockSizeStats; +fn analyze_block_size_stats(stt: &ix_compile::compile::CompileState) { + use ix_compile::compile::BlockSizeStats; // Check if hash-consed size tracking was enabled - let tracking_enabled = crate::ix::compile::TRACK_HASH_CONSED_SIZE + let tracking_enabled = ix_compile::compile::TRACK_HASH_CONSED_SIZE .load(std::sync::atomic::Ordering::Relaxed); if !tracking_enabled { println!("\n=== Block Size Analysis ==="); diff --git a/src/ffi/iroh.rs b/crates/ffi/src/lean_iroh.rs similarity index 100% rename from src/ffi/iroh.rs rename to crates/ffi/src/lean_iroh.rs diff --git a/src/ffi/ixon.rs b/crates/ffi/src/lean_ixon.rs similarity index 100% rename from src/ffi/ixon.rs rename to crates/ffi/src/lean_ixon.rs diff --git a/src/ffi/ixon/compare.rs b/crates/ffi/src/lean_ixon/compare.rs similarity index 96% rename from src/ffi/ixon/compare.rs rename to crates/ffi/src/lean_ixon/compare.rs index aa82724b..6890d89d 100644 --- a/src/ffi/ixon/compare.rs +++ b/crates/ffi/src/lean_ixon/compare.rs @@ -2,14 +2,16 @@ use std::collections::HashMap; -use crate::ix::compile::{BlockCache, CompileState, compile_env, compile_expr}; -use crate::ix::env::Name; -use crate::ix::ixon::serialize::put_expr; -use crate::ix::mutual::MutCtx; use crate::lean::{LeanIxBlockCompareDetail, LeanIxBlockCompareResult}; +use ix_common::env::Name; +use ix_compile::compile::{ + BlockCache, CompileState, compile_env, compile_expr, +}; +use ix_compile::mutual::MutCtx; +use ixon::serialize::put_expr; use lean_ffi::object::{LeanBorrowed, LeanByteArray, LeanList, LeanOwned}; -use crate::ffi::lean_env::{ +use crate::lean_env::{ Cache as LeanCache, GlobalCache, decode_expr, decode_name, }; @@ -195,7 +197,7 @@ pub unsafe extern "C" fn rs_free_compiled_env(ptr: *mut RustBlockEnv) { pub extern "C" fn rs_build_compiled_env( env_consts_ptr: LeanList>, ) -> *mut RustBlockEnv { - use crate::ffi::lean_env::decode_env; + use crate::lean_env::decode_env; // Decode Lean environment let rust_env = decode_env(env_consts_ptr); diff --git a/src/ffi/ixon/constant.rs b/crates/ffi/src/lean_ixon/constant.rs similarity index 97% rename from src/ffi/ixon/constant.rs rename to crates/ffi/src/lean_ixon/constant.rs index eabde98b..d5fe112f 100644 --- a/src/ffi/ixon/constant.rs +++ b/crates/ffi/src/lean_ixon/constant.rs @@ -6,14 +6,6 @@ use std::sync::Arc; -use crate::ix::ixon::constant::{ - Axiom as IxonAxiom, Constant as IxonConstant, - ConstantInfo as IxonConstantInfo, Constructor as IxonConstructor, - ConstructorProj, DefKind, Definition as IxonDefinition, DefinitionProj, - Inductive as IxonInductive, InductiveProj, MutConst, - Quotient as IxonQuotient, Recursor as IxonRecursor, RecursorProj, - RecursorRule as IxonRecursorRule, -}; use crate::lean::{ LeanIxAddress, LeanIxonAxiom, LeanIxonConstant, LeanIxonConstantInfo, LeanIxonConstructor, LeanIxonConstructorProj, LeanIxonDefinition, @@ -21,6 +13,14 @@ use crate::lean::{ LeanIxonInductiveProj, LeanIxonMutConst, LeanIxonQuotient, LeanIxonRecursor, LeanIxonRecursorProj, LeanIxonRecursorRule, LeanIxonUniv, }; +use ixon::constant::{ + Axiom as IxonAxiom, Constant as IxonConstant, + ConstantInfo as IxonConstantInfo, Constructor as IxonConstructor, + ConstructorProj, DefKind, Definition as IxonDefinition, DefinitionProj, + Inductive as IxonInductive, InductiveProj, MutConst, + Quotient as IxonQuotient, Recursor as IxonRecursor, RecursorProj, + RecursorRule as IxonRecursorRule, +}; #[cfg(feature = "test-ffi")] use lean_ffi::object::LeanBorrowed; use lean_ffi::object::{LeanArray, LeanOwned, LeanRef}; @@ -47,9 +47,9 @@ impl LeanIxonDefinition { }; ctor.set_num_8(0, kind_val); let safety_val: u8 = match def.safety { - crate::ix::env::DefinitionSafety::Unsafe => 0, - crate::ix::env::DefinitionSafety::Safe => 1, - crate::ix::env::DefinitionSafety::Partial => 2, + ix_common::env::DefinitionSafety::Unsafe => 0, + ix_common::env::DefinitionSafety::Safe => 1, + ix_common::env::DefinitionSafety::Partial => 2, }; ctor.set_num_8(1, safety_val); ctor @@ -75,9 +75,9 @@ impl LeanIxonDefinition { }; let safety_val = self.get_num_8(1); let safety = match safety_val { - 0 => crate::ix::env::DefinitionSafety::Unsafe, - 1 => crate::ix::env::DefinitionSafety::Safe, - 2 => crate::ix::env::DefinitionSafety::Partial, + 0 => ix_common::env::DefinitionSafety::Unsafe, + 1 => ix_common::env::DefinitionSafety::Safe, + 2 => ix_common::env::DefinitionSafety::Partial, _ => panic!("Invalid DefinitionSafety: {}", safety_val), }; IxonDefinition { kind, safety, lvls, typ, value } @@ -210,10 +210,10 @@ impl LeanIxonQuotient { ctor.set_obj(0, typ_obj); ctor.set_num_64(0, quot.lvls); let kind_val: u8 = match quot.kind { - crate::ix::env::QuotKind::Type => 0, - crate::ix::env::QuotKind::Ctor => 1, - crate::ix::env::QuotKind::Lift => 2, - crate::ix::env::QuotKind::Ind => 3, + ix_common::env::QuotKind::Type => 0, + ix_common::env::QuotKind::Ctor => 1, + ix_common::env::QuotKind::Lift => 2, + ix_common::env::QuotKind::Ind => 3, }; ctor.set_num_8(0, kind_val); ctor @@ -229,10 +229,10 @@ impl LeanIxonQuotient { let lvls = self.get_num_64(0); let kind_val = self.get_num_8(0); let kind = match kind_val { - 0 => crate::ix::env::QuotKind::Type, - 1 => crate::ix::env::QuotKind::Ctor, - 2 => crate::ix::env::QuotKind::Lift, - 3 => crate::ix::env::QuotKind::Ind, + 0 => ix_common::env::QuotKind::Type, + 1 => ix_common::env::QuotKind::Ctor, + 2 => ix_common::env::QuotKind::Lift, + 3 => ix_common::env::QuotKind::Ind, _ => panic!("Invalid QuotKind: {}", kind_val), }; IxonQuotient { kind, lvls, typ } diff --git a/src/ffi/ixon/enums.rs b/crates/ffi/src/lean_ixon/enums.rs similarity index 97% rename from src/ffi/ixon/enums.rs rename to crates/ffi/src/lean_ixon/enums.rs index 0afa0593..54fa7a4f 100644 --- a/src/ffi/ixon/enums.rs +++ b/crates/ffi/src/lean_ixon/enums.rs @@ -1,10 +1,10 @@ //! Ixon enum types: DefKind, DefinitionSafety, QuotKind build/decode/roundtrip FFI. -use crate::ix::env::{DefinitionSafety, QuotKind}; -use crate::ix::ixon::constant::DefKind; use crate::lean::{ LeanIxonDefKind, LeanIxonDefinitionSafety, LeanIxonQuotKind, }; +use ix_common::env::{DefinitionSafety, QuotKind}; +use ixon::constant::DefKind; #[cfg(feature = "test-ffi")] use lean_ffi::object::LeanBorrowed; use lean_ffi::object::{LeanOwned, LeanRef}; diff --git a/src/ffi/ixon/env.rs b/crates/ffi/src/lean_ixon/env.rs similarity index 97% rename from src/ffi/ixon/env.rs rename to crates/ffi/src/lean_ixon/env.rs index 02d3b27b..120dd26e 100644 --- a/src/ffi/ixon/env.rs +++ b/crates/ffi/src/lean_ixon/env.rs @@ -3,23 +3,23 @@ //! Provides full decode/build cycle for RawEnv and its component types: //! RawConst, RawNamed, RawBlob, RawComm. -use crate::ix::address::Address; -use crate::ix::env::Name; -use crate::ix::ixon::comm::Comm; -use crate::ix::ixon::constant::Constant as IxonConstant; -use crate::ix::ixon::env::{Env as IxonEnv, Named as IxonNamed}; -use crate::ix::ixon::merkle::merkle_root_canonical; -use crate::ix::ixon::metadata::ConstantMeta; use crate::lean::{ LeanIxName, LeanIxonComm, LeanIxonConstant, LeanIxonConstantMeta, LeanIxonRawBlob, LeanIxonRawComm, LeanIxonRawConst, LeanIxonRawEnv, LeanIxonRawNameEntry, LeanIxonRawNamed, }; +use ix_common::address::Address; +use ix_common::env::Name; +use ixon::comm::Comm; +use ixon::constant::Constant as IxonConstant; +use ixon::env::{Env as IxonEnv, Named as IxonNamed}; +use ixon::merkle::merkle_root_canonical; +use ixon::metadata::ConstantMeta; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanByteArray, LeanExcept, LeanOwned, LeanRef, }; -use crate::ffi::builder::LeanBuildCache; +use crate::builder::LeanBuildCache; use crate::lean::LeanIxAddress; // ============================================================================= diff --git a/src/ffi/ixon/expr.rs b/crates/ffi/src/lean_ixon/expr.rs similarity index 99% rename from src/ffi/ixon/expr.rs rename to crates/ffi/src/lean_ixon/expr.rs index 4fb71091..cea24163 100644 --- a/src/ffi/ixon/expr.rs +++ b/crates/ffi/src/lean_ixon/expr.rs @@ -2,8 +2,8 @@ use std::sync::Arc; -use crate::ix::ixon::expr::Expr as IxonExpr; use crate::lean::LeanIxonExpr; +use ixon::expr::Expr as IxonExpr; use lean_ffi::object::{LeanArray, LeanBorrowed, LeanOwned, LeanRef}; /// Decode Array UInt64 from Lean. diff --git a/src/ffi/ixon/meta.rs b/crates/ffi/src/lean_ixon/meta.rs similarity index 99% rename from src/ffi/ixon/meta.rs rename to crates/ffi/src/lean_ixon/meta.rs index 3962f65d..13db8ec0 100644 --- a/src/ffi/ixon/meta.rs +++ b/crates/ffi/src/lean_ixon/meta.rs @@ -2,19 +2,19 @@ //! //! Includes: DataValue, KVMap, ExprMetaData, ExprMetaArena, ConstantMeta, Named, Comm -use crate::ix::address::Address; -use crate::ix::env::BinderInfo; -use crate::ix::ixon::Comm; -use crate::ix::ixon::env::Named; -use crate::ix::ixon::metadata::{ - ConstantMeta, ConstantMetaInfo, DataValue as IxonDataValue, ExprMeta, - ExprMetaData, KVMap, -}; use crate::lean::{ LeanIxReducibilityHints, LeanIxonComm, LeanIxonConstantMeta, LeanIxonDataValue, LeanIxonExprMetaArena, LeanIxonExprMetaData, LeanIxonNamed, }; +use ix_common::address::Address; +use ix_common::env::BinderInfo; +use ixon::Comm; +use ixon::env::Named; +use ixon::metadata::{ + ConstantMeta, ConstantMetaInfo, DataValue as IxonDataValue, ExprMeta, + ExprMetaData, KVMap, +}; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanOption, LeanOwned, LeanProd, LeanRef, }; diff --git a/src/ffi/ixon/serialize.rs b/crates/ffi/src/lean_ixon/serialize.rs similarity index 97% rename from src/ffi/ixon/serialize.rs rename to crates/ffi/src/lean_ixon/serialize.rs index 5106a9b6..68061c03 100644 --- a/src/ffi/ixon/serialize.rs +++ b/crates/ffi/src/lean_ixon/serialize.rs @@ -5,13 +5,13 @@ use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::ixon::serialize::put_expr; -use crate::ix::ixon::sharing::hash_expr; -use crate::ix::ixon::univ::put_univ; use crate::lean::{ LeanIxAddress, LeanIxonConstant, LeanIxonExpr, LeanIxonRawEnv, LeanIxonUniv, }; +use ix_common::address::Address; +use ixon::serialize::put_expr; +use ixon::sharing::hash_expr; +use ixon::univ::put_univ; use lean_ffi::object::{LeanBorrowed, LeanByteArray, LeanOwned}; /// Check if Lean's computed hash matches Rust's computed hash. @@ -77,7 +77,7 @@ pub extern "C" fn rs_eq_env_serialization( raw_env_obj: LeanIxonRawEnv>, bytes_obj: LeanByteArray>, ) -> bool { - use crate::ix::ixon::env::Env; + use ixon::env::Env; let debug = std::env::var("IX_DEBUG_SERDE").is_ok(); let decoded = raw_env_obj.decode(); @@ -246,7 +246,7 @@ pub extern "C" fn rs_eq_env_serialization( extern "C" fn rs_env_serde_roundtrip( lean_bytes_obj: LeanByteArray, ) -> bool { - use crate::ix::ixon::env::Env; + use ixon::env::Env; // Get bytes from Lean ByteArray let lean_bytes = lean_bytes_obj.as_bytes().to_vec(); @@ -294,7 +294,7 @@ extern "C" fn rs_env_serde_roundtrip( extern "C" fn rs_env_serde_check( lean_bytes_obj: LeanByteArray, ) -> bool { - use crate::ix::ixon::env::Env; + use ixon::env::Env; // Get bytes from Lean ByteArray let lean_bytes = lean_bytes_obj.as_bytes().to_vec(); diff --git a/src/ffi/ixon/sharing.rs b/crates/ffi/src/lean_ixon/sharing.rs similarity index 95% rename from src/ffi/ixon/sharing.rs rename to crates/ffi/src/lean_ixon/sharing.rs index 85065081..9811fb63 100644 --- a/src/ffi/ixon/sharing.rs +++ b/crates/ffi/src/lean_ixon/sharing.rs @@ -2,12 +2,10 @@ use std::sync::Arc; -use crate::ix::ixon::expr::Expr as IxonExpr; -use crate::ix::ixon::serialize::put_expr; -use crate::ix::ixon::sharing::{ - analyze_block, build_sharing_vec, decide_sharing, -}; use crate::lean::LeanIxonExpr; +use ixon::expr::Expr as IxonExpr; +use ixon::serialize::put_expr; +use ixon::sharing::{analyze_block, build_sharing_vec, decide_sharing}; use lean_ffi::object::{LeanArray, LeanBorrowed, LeanByteArray, LeanOwned}; /// FFI: Debug sharing analysis - print usage counts for subterms with usage >= 2. @@ -23,7 +21,7 @@ pub extern "C" fn rs_debug_sharing_analysis( let (info_map, _ptr_to_hash, topo_order) = analyze_block(&exprs, false); let effective_sizes = - crate::ix::ixon::sharing::compute_effective_sizes(&info_map, &topo_order); + ixon::sharing::compute_effective_sizes(&info_map, &topo_order); println!("[Rust] Found {} unique subterms", info_map.len()); diff --git a/src/ffi/ixon/univ.rs b/crates/ffi/src/lean_ixon/univ.rs similarity index 98% rename from src/ffi/ixon/univ.rs rename to crates/ffi/src/lean_ixon/univ.rs index c85dde83..57b8eab1 100644 --- a/src/ffi/ixon/univ.rs +++ b/crates/ffi/src/lean_ixon/univ.rs @@ -2,8 +2,8 @@ use std::sync::Arc; -use crate::ix::ixon::univ::Univ; use crate::lean::LeanIxonUniv; +use ixon::univ::Univ; use lean_ffi::object::{LeanArray, LeanBorrowed, LeanOwned, LeanRef}; impl LeanIxonUniv { diff --git a/crates/ffi/src/lib.rs b/crates/ffi/src/lib.rs new file mode 100644 index 00000000..fd7daf02 --- /dev/null +++ b/crates/ffi/src/lib.rs @@ -0,0 +1,60 @@ +// `_iroh` provides dummy fallbacks when the `net` feature is disabled or on +// `aarch64-darwin` (where iroh doesn't work). Lean and C don't support feature +// flags, so we always expose iroh symbols — they just panic with an error +// message when called without `net`. +#[cfg(any( + not(feature = "net"), + all(target_os = "macos", target_arch = "aarch64") +))] +pub mod _iroh; +pub mod aiur; +pub mod byte_array; +#[cfg(all( + feature = "net", + not(all(target_os = "macos", target_arch = "aarch64")) +))] +pub mod iroh; +pub mod keccak; +pub mod lean_env; +pub mod texray; +#[cfg(all( + feature = "net", + not(all(target_os = "macos", target_arch = "aarch64")) +))] +pub mod lean_iroh; +pub mod unsigned; + +pub mod builder; +pub mod compile; +pub mod graph; +pub mod ix; +pub mod kernel; +pub mod lean_ixon; +pub mod primitives; +#[cfg(feature = "test-ffi")] +pub mod refcount; + +pub mod lean; +mod sha256; + +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + +#[cfg(feature = "test-ffi")] +use lean_ffi::object::{ + LeanArray, LeanBorrowed, LeanByteArray, LeanOwned, LeanRef, +}; + +#[cfg(feature = "test-ffi")] +#[unsafe(no_mangle)] +extern "C" fn rs_boxed_u32s_are_equivalent_to_bytes( + u32s: LeanArray, + bytes: LeanByteArray>, +) -> bool { + let u32s_flat: Vec = u32s + .map(|elem| elem.unbox_u32()) + .into_iter() + .flat_map(u32::to_le_bytes) + .collect(); + u32s_flat == bytes.as_bytes() +} diff --git a/src/ffi/primitives.rs b/crates/ffi/src/primitives.rs similarity index 91% rename from src/ffi/primitives.rs rename to crates/ffi/src/primitives.rs index c73e1448..89408189 100644 --- a/src/ffi/primitives.rs +++ b/crates/ffi/src/primitives.rs @@ -4,6 +4,7 @@ //! (ix-specific types not covered by the lean-ffi test suite). use lean_ffi::nat::Nat; +use lean_ffi::object::LeanNat; #[cfg(feature = "test-ffi")] use lean_ffi::object::{LeanArray, LeanCtor, LeanOwned}; use lean_ffi::object::{LeanBorrowed, LeanRef}; @@ -34,8 +35,8 @@ fn build_assoc_list_nat_nat(pairs: &[(Nat, Nat)]) -> LeanOwned { let mut list = LeanOwned::box_usize(0); // nil for (k, v) in pairs.iter().rev() { let cons = LeanCtor::alloc(1, 3, 0); // AssocList.cons - cons.set(0, Nat::to_lean(k)); - cons.set(1, Nat::to_lean(v)); + cons.set(0, LeanNat::from_nat(k)); + cons.set(1, LeanNat::from_nat(v)); cons.set(2, list); list = cons.into(); } @@ -53,7 +54,7 @@ pub extern "C" fn rs_roundtrip_dhashmap_raw_nat_nat( } let raw_ctor = raw_ptr.as_ctor(); - let size = Nat::from_obj(&raw_ctor.get(0)); + let size = LeanNat::to_nat(&raw_ctor.get(0)); let buckets = raw_ctor.get(1).as_array(); // Decode and rebuild buckets @@ -85,15 +86,15 @@ pub extern "C" fn rs_roundtrip_dhashmap_raw_nat_nat( let old_bucket = new_buckets.get(bucket_idx).to_owned_ref(); let new_bucket = LeanCtor::alloc(1, 3, 0); - new_bucket.set(0, Nat::to_lean(k)); - new_bucket.set(1, Nat::to_lean(v)); + new_bucket.set(0, LeanNat::from_nat(k)); + new_bucket.set(1, LeanNat::from_nat(v)); new_bucket.set(2, old_bucket); new_buckets.set(bucket_idx, new_bucket); } // Build Raw let raw = LeanCtor::alloc(0, 2, 0); - raw.set(0, Nat::to_lean(&size)); + raw.set(0, LeanNat::from_nat(&size)); raw.set(1, new_buckets); raw.into() } @@ -119,7 +120,7 @@ pub extern "C" fn rs_roundtrip_hashmap_nat_nat( map_ptr: LeanCtor>, ) -> LeanOwned { // Due to unboxing, map_ptr points directly to Raw - let size = Nat::from_obj(&map_ptr.get(0)); + let size = LeanNat::to_nat(&map_ptr.get(0)); let buckets = map_ptr.get(1).as_array(); // Decode buckets (Array of AssocLists) @@ -160,8 +161,8 @@ pub extern "C" fn rs_roundtrip_hashmap_nat_nat( // Build AssocList.cons key value tail (tag 1, 3 fields) let new_bucket = LeanCtor::alloc(1, 3, 0); - new_bucket.set(0, Nat::to_lean(k)); - new_bucket.set(1, Nat::to_lean(v)); + new_bucket.set(0, LeanNat::from_nat(k)); + new_bucket.set(1, LeanNat::from_nat(v)); new_bucket.set(2, old_bucket); new_buckets.set(bucket_idx, new_bucket); } @@ -169,7 +170,7 @@ pub extern "C" fn rs_roundtrip_hashmap_nat_nat( // Build Raw (ctor 0, 2 fields: size, buckets) // Due to unboxing, this IS the HashMap let raw = LeanCtor::alloc(0, 2, 0); - raw.set(0, Nat::to_lean(&size)); + raw.set(0, LeanNat::from_nat(&size)); raw.set(1, new_buckets); raw.into() } @@ -188,7 +189,7 @@ pub fn decode_assoc_list_nat_nat(obj: LeanBorrowed<'_>) -> Vec<(Nat, Nat)> { let key = ctor.get(0); let val = ctor.get(1); let next = ctor.get(2).as_raw(); - result.push((Nat::from_obj(&key), Nat::from_obj(&val))); + result.push((LeanNat::to_nat(&key), LeanNat::to_nat(&val))); current = unsafe { LeanBorrowed::from_raw(next) }; } diff --git a/src/ffi/refcount.rs b/crates/ffi/src/refcount.rs similarity index 96% rename from src/ffi/refcount.rs rename to crates/ffi/src/refcount.rs index f5edd77c..a6834599 100644 --- a/src/ffi/refcount.rs +++ b/crates/ffi/src/refcount.rs @@ -17,11 +17,12 @@ use std::thread; use lean_ffi::LeanShared; use lean_ffi::nat::Nat; +use lean_ffi::object::LeanNat; use lean_ffi::object::{ LeanArray, LeanBorrowed, LeanList, LeanOwned, LeanRef, LeanString, }; -use crate::ffi::builder::LeanBuildCache; +use crate::builder::LeanBuildCache; use crate::lean::{LeanIxExpr, LeanIxLevel, LeanIxName}; // ============================================================================= @@ -92,7 +93,7 @@ pub extern "C" fn rs_refcount_deep_borrow_expr( _ => 1, } } - Nat::from(count_nodes(&expr)).to_lean().into() + LeanNat::from_nat(&Nat::from(count_nodes(&expr))).into() } // ============================================================================= @@ -109,7 +110,7 @@ pub extern "C" fn rs_refcount_owned_array_drop( for i in 0..count { let _ = LeanIxName(arr.get(i)).decode(); } - Nat::from(count as u64).to_lean().into() + LeanNat::from_nat(&Nat::from(count as u64)).into() } /// Take an owned List of Exprs, consume and count. @@ -122,7 +123,7 @@ pub extern "C" fn rs_refcount_owned_list_drop( let _ = LeanIxExpr(elem).decode(); count += 1; } - Nat::from(count).to_lean().into() + LeanNat::from_nat(&Nat::from(count)).into() } // ============================================================================= @@ -140,7 +141,8 @@ pub extern "C" fn rs_refcount_clone_and_compare( let decoded1 = owned1.decode(); let decoded2 = owned2.decode(); // owned1 and owned2 both dropped → two lean_dec calls - Nat::from(if decoded1 == decoded2 { 1u64 } else { 0u64 }).to_lean().into() + LeanNat::from_nat(&Nat::from(if decoded1 == decoded2 { 1u64 } else { 0u64 })) + .into() } // ============================================================================= @@ -180,7 +182,7 @@ pub extern "C" fn rs_refcount_nested_borrow( let _level = LeanIxLevel(pair.get(1)).decode(); count += 1; } - Nat::from(count).to_lean().into() + LeanNat::from_nat(&Nat::from(count)).into() } // ============================================================================= @@ -313,7 +315,7 @@ pub extern "C" fn rs_mt_parallel_decode_names( .collect(); let total: u64 = handles.into_iter().map(|h| h.join().unwrap()).sum(); - Nat::from(total).to_lean().into() + LeanNat::from_nat(&Nat::from(total)).into() } /// Mark an array of Ix.Exprs as MT, decode in parallel from N threads. @@ -352,7 +354,7 @@ pub extern "C" fn rs_mt_parallel_decode_exprs( .collect(); let total: u64 = handles.into_iter().map(|h| h.join().unwrap()).sum(); - Nat::from(total).to_lean().into() + LeanNat::from_nat(&Nat::from(total)).into() } /// Parallel roundtrip: mark array of Names as MT, each thread decodes @@ -364,7 +366,7 @@ pub extern "C" fn rs_mt_parallel_roundtrip_names( arr: LeanArray>, n_threads: usize, ) -> LeanArray { - use crate::ix::env::Name; + use ix_common::env::Name; let shared = LeanShared::new(arr.inner().to_owned_ref()); let len = arr.len(); @@ -428,5 +430,5 @@ pub extern "C" fn rs_mt_shared_expr_stress( .collect(); let total: u64 = handles.into_iter().map(|h| h.join().unwrap()).sum(); - Nat::from(total).to_lean().into() + LeanNat::from_nat(&Nat::from(total)).into() } diff --git a/src/sha256.rs b/crates/ffi/src/sha256.rs similarity index 100% rename from src/sha256.rs rename to crates/ffi/src/sha256.rs diff --git a/src/ffi/texray.rs b/crates/ffi/src/texray.rs similarity index 100% rename from src/ffi/texray.rs rename to crates/ffi/src/texray.rs diff --git a/src/ffi/unsigned.rs b/crates/ffi/src/unsigned.rs similarity index 100% rename from src/ffi/unsigned.rs rename to crates/ffi/src/unsigned.rs diff --git a/crates/ixon/Cargo.toml b/crates/ixon/Cargo.toml new file mode 100644 index 00000000..d2c0183c --- /dev/null +++ b/crates/ixon/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "ixon" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +bignat = { workspace = true } +blake3 = { workspace = true } +dashmap = { workspace = true } +indexmap = { workspace = true } +ix-common = { workspace = true } +memmap2 = { workspace = true } +num-bigint = { workspace = true } +rustc-hash = { workspace = true } +sha2 = { workspace = true } +tiny-keccak = { workspace = true } + +[target.'cfg(not(target_arch = "riscv64"))'.dependencies] +dashmap = { workspace = true, features = ["rayon"] } +rayon = { workspace = true } + +[dev-dependencies] +ix-common = { workspace = true, features = ["quickcheck"] } +quickcheck = { workspace = true } +quickcheck_macros = { workspace = true } + +[lints] +workspace = true diff --git a/src/ix/ixon/assumption_tree.rs b/crates/ixon/src/assumption_tree.rs similarity index 99% rename from src/ix/ixon/assumption_tree.rs rename to crates/ixon/src/assumption_tree.rs index 4cf61d2b..05500c2f 100644 --- a/src/ix/ixon/assumption_tree.rs +++ b/crates/ixon/src/assumption_tree.rs @@ -36,7 +36,7 @@ //! `leaves()` clean (it returns only real leaves, not the synthetic //! padding addresses). -use crate::ix::address::Address; +use ix_common::address::Address; use super::merkle::{MerklePath, leaf_hash, node_hash, zero_address}; use super::proof::{FLAG_CLAIM, VARIANT_ASSUMPTION_TREE}; diff --git a/src/ix/ixon/comm.rs b/crates/ixon/src/comm.rs similarity index 98% rename from src/ix/ixon/comm.rs rename to crates/ixon/src/comm.rs index a27afcb2..9de866ca 100644 --- a/src/ix/ixon/comm.rs +++ b/crates/ixon/src/comm.rs @@ -3,7 +3,7 @@ #![allow(clippy::map_err_ignore)] #![allow(clippy::needless_pass_by_value)] -use crate::ix::address::Address; +use ix_common::address::Address; use super::tag::Tag4; @@ -81,6 +81,7 @@ impl Comm { mod tests { use super::*; use quickcheck::Arbitrary; + use quickcheck_macros::quickcheck; impl Arbitrary for Comm { fn arbitrary(g: &mut quickcheck::Gen) -> Self { diff --git a/src/ix/ixon/constant.rs b/crates/ixon/src/constant.rs similarity index 94% rename from src/ix/ixon/constant.rs rename to crates/ixon/src/constant.rs index 0f311566..12cc881b 100644 --- a/src/ix/ixon/constant.rs +++ b/crates/ixon/src/constant.rs @@ -10,8 +10,8 @@ use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::env::{DefinitionSafety, QuotKind}; +use ix_common::address::Address; +use ix_common::env::{DefinitionSafety, QuotKind}; use super::expr::Expr; use super::univ::Univ; @@ -310,10 +310,11 @@ pub fn ctor_proj_constant(idx: u64, cidx: u64, block: Address) -> Constant { #[cfg(test)] pub mod tests { use super::*; - use crate::ix::env::{DefinitionSafety, QuotKind}; - use crate::ix::ixon::expr::tests::arbitrary_expr; - use crate::ix::ixon::tests::gen_range; + use crate::expr::tests::arbitrary_expr; + use crate::tests::gen_range; + use ix_common::env::{DefinitionSafety, QuotKind}; use quickcheck::{Arbitrary, Gen}; + use quickcheck_macros::quickcheck; impl Arbitrary for DefKind { fn arbitrary(g: &mut Gen) -> Self { @@ -325,27 +326,6 @@ pub mod tests { } } - impl Arbitrary for DefinitionSafety { - fn arbitrary(g: &mut Gen) -> Self { - match u8::arbitrary(g) % 3 { - 0 => DefinitionSafety::Unsafe, - 1 => DefinitionSafety::Safe, - _ => DefinitionSafety::Partial, - } - } - } - - impl Arbitrary for QuotKind { - fn arbitrary(g: &mut Gen) -> Self { - match u8::arbitrary(g) % 4 { - 0 => QuotKind::Type, - 1 => QuotKind::Ctor, - 2 => QuotKind::Lift, - _ => QuotKind::Ind, - } - } - } - pub fn gen_sharing(g: &mut Gen) -> Vec> { (0..gen_range(g, 0..4)).map(|_| arbitrary_expr(g)).collect() } @@ -355,7 +335,7 @@ pub mod tests { } pub fn gen_univs(g: &mut Gen) -> Vec> { - use crate::ix::ixon::univ::tests::arbitrary_univ; + use crate::univ::tests::arbitrary_univ; (0..gen_range(g, 0..4)).map(|_| arbitrary_univ(g)).collect() } diff --git a/src/ix/ixon/env.rs b/crates/ixon/src/env.rs similarity index 88% rename from src/ix/ixon/env.rs rename to crates/ixon/src/env.rs index e8363774..1e27774d 100644 --- a/src/ix/ixon/env.rs +++ b/crates/ixon/src/env.rs @@ -1,17 +1,17 @@ //! Environment for storing Ixon data. -use dashmap::DashMap; use rustc_hash::{FxHashMap, FxHashSet}; use std::collections::VecDeque; use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::env::{Name, ReducibilityHints}; +use ix_common::address::Address; +use ix_common::env::{Name, ReducibilityHints}; use super::comm::Comm; use super::constant::Constant; use super::lazy::LazyConstant; -use super::metadata::ConstantMeta; +use super::map::IxonMap; +use super::metadata::{ConstantMeta, ConstantMetaInfo}; /// A named constant with metadata. #[derive(Clone, Debug)] @@ -43,7 +43,7 @@ impl Named { /// correctly permute source-order aux motives/minors into canonical /// positions. Both arrays have one entry per source-walk-discovered aux. /// -/// This lives in `ixon::env` (not `compile::surgery`, where it originated) +/// This lives in `ixon::env` (not `ix_compile::surgery`, where it originated) /// so it can be persisted into the serialized Ixon environment as a /// side-table on [`Env::aux_layouts`]. The surgery layer re-exports it. /// @@ -75,15 +75,15 @@ pub struct AuxLayout { pub struct Env { /// Alpha-invariant constants: Address -> LazyConstant (raw bytes + /// optional materialized cache; see [`LazyConstant`]). - pub consts: DashMap, + pub consts: IxonMap, /// Named references: Name -> (constant address, metadata, ctx) - pub named: DashMap, + pub named: IxonMap, /// Raw data blobs: Address -> bytes - pub blobs: DashMap>, + pub blobs: IxonMap>, /// Hash-consed Lean.Name components: Address -> Name - pub names: DashMap, + pub names: IxonMap, /// Cryptographic commitments: commitment Address -> Comm - pub comms: DashMap, + pub comms: IxonMap, /// Reducibility hints sidecar harvested by [`Env::get_anon`] from the /// otherwise-discarded Named section. Keyed by the constant's /// projection/standalone address (i.e. `Named.addr` — the address the @@ -103,16 +103,22 @@ pub struct Env { impl Env { pub fn new() -> Self { Env { - consts: DashMap::new(), - named: DashMap::new(), - blobs: DashMap::new(), - names: DashMap::new(), - comms: DashMap::new(), + consts: IxonMap::new(), + named: IxonMap::new(), + blobs: IxonMap::new(), + names: IxonMap::new(), + comms: IxonMap::new(), anon_hints: FxHashMap::default(), } } /// Store a blob and return its content address. + /// + /// Host-only because `IxonMap` is `DashMap` here (interior-mutable `&self` + /// inserts). On `riscv64` `IxonMap` is `FxHashMap`, which requires `&mut`; + /// the guest builds `Env` via `Env::get` deserialization and doesn't need + /// the store helpers. + #[cfg(not(target_arch = "riscv64"))] pub fn store_blob(&self, bytes: Vec) -> Address { let addr = Address::hash(&bytes); self.blobs.insert(addr.clone(), bytes); @@ -129,12 +135,17 @@ impl Env { /// Serializes the constant once and pre-populates the /// [`LazyConstant`] cache so subsequent `Env::put` is a memcpy and /// the first `get_const` call is free. + /// + /// Host-only — see `store_blob`. + #[cfg(not(target_arch = "riscv64"))] pub fn store_const(&self, addr: Address, constant: Constant) { self.consts.insert(addr, LazyConstant::from_constant(constant)); } /// Store an already-serialized constant under `addr` (lazy load path). /// `bytes` must be exactly what `Constant::put` produced for `addr`. + /// Host-only — see `store_blob`. + #[cfg(not(target_arch = "riscv64"))] pub fn store_const_lazy(&self, addr: Address, bytes: Arc<[u8]>) { self.consts.insert(addr, LazyConstant::from_bytes(bytes)); } @@ -143,6 +154,8 @@ impl Env { /// `(mmap, offset, len)` must reference exactly what `Constant::put` /// produced for `addr`. Used by [`Env::get_anon_mmap`] to avoid /// heap-copying on-disk bytes — the OS page cache backs the slice. + /// Host-only — see `store_blob`. + #[cfg(not(target_arch = "riscv64"))] pub fn store_const_lazy_mmap( &self, addr: Address, @@ -175,7 +188,8 @@ impl Env { self.consts.get(addr).map(|r| Arc::from(r.value().raw_bytes())) } - /// Register a named constant. + /// Register a named constant. Host-only — see `store_blob`. + #[cfg(not(target_arch = "riscv64"))] pub fn register_name(&self, name: Name, named: Named) { self.named.insert(name, named); } @@ -185,7 +199,8 @@ impl Env { self.named.get(name).map(|r| r.clone()) } - /// Store a hash-consed name component. + /// Store a hash-consed name component. Host-only — see `store_blob`. + #[cfg(not(target_arch = "riscv64"))] pub fn store_name(&self, addr: Address, name: Name) { self.names.insert(addr, name); } @@ -195,7 +210,8 @@ impl Env { self.names.get(addr).map(|r| r.clone()) } - /// Store a commitment. + /// Store a commitment. Host-only — see `store_blob`. + #[cfg(not(target_arch = "riscv64"))] pub fn store_comm(&self, addr: Address, comm: Comm) { self.comms.insert(addr, comm); } @@ -215,6 +231,20 @@ impl Env { self.named.len() } + /// Addresses of the named constants the kernel typechecker would + /// iterate via `check_const` — every entry in `env.named` minus the + /// `Muts` mutual-block pointers (which aren't standalone checkables). + /// Matches `crates/ffi/src/kernel.rs::all_checkable_ixon_names` but + /// returns addresses rather than names and skips the sort. + pub fn checkable_addrs(&self) -> Vec
{ + self + .named + .iter() + .filter(|e| !matches!(e.value().meta.info, ConstantMetaInfo::Muts { .. })) + .map(|e| e.value().addr.clone()) + .collect() + } + /// Number of hash-consed name components. pub fn name_count(&self) -> usize { self.names.len() @@ -276,28 +306,31 @@ impl Env { } impl Clone for Env { + // `mut` is only needed on `riscv64` where `IxonMap` wraps `FxHashMap` and + // `insert` takes `&mut self`; on host `DashMap::insert` takes `&self`. + #[cfg_attr(not(target_arch = "riscv64"), allow(unused_mut))] fn clone(&self) -> Self { - let consts = DashMap::new(); + let mut consts = IxonMap::new(); for entry in self.consts.iter() { consts.insert(entry.key().clone(), entry.value().clone()); } - let named = DashMap::new(); + let mut named = IxonMap::new(); for entry in self.named.iter() { named.insert(entry.key().clone(), entry.value().clone()); } - let blobs = DashMap::new(); + let mut blobs = IxonMap::new(); for entry in self.blobs.iter() { blobs.insert(entry.key().clone(), entry.value().clone()); } - let names = DashMap::new(); + let mut names = IxonMap::new(); for entry in self.names.iter() { names.insert(entry.key().clone(), entry.value().clone()); } - let comms = DashMap::new(); + let mut comms = IxonMap::new(); for entry in self.comms.iter() { comms.insert(entry.key().clone(), entry.value().clone()); } @@ -316,9 +349,9 @@ impl Clone for Env { #[cfg(test)] mod tests { use super::*; - use crate::ix::env::Name; - use crate::ix::ixon::constant::{Axiom, Constant, ConstantInfo}; - use crate::ix::ixon::expr::Expr; + use crate::constant::{Axiom, Constant, ConstantInfo}; + use crate::expr::Expr; + use ix_common::env::Name; use std::sync::Arc; fn n(s: &str) -> Name { diff --git a/src/ix/ixon/error.rs b/crates/ixon/src/error.rs similarity index 99% rename from src/ix/ixon/error.rs rename to crates/ixon/src/error.rs index 26f22334..0e2c8462 100644 --- a/src/ix/ixon/error.rs +++ b/crates/ixon/src/error.rs @@ -1,6 +1,6 @@ //! Custom error types for Ixon serialization and compilation. -use crate::ix::address::Address; +use ix_common::address::Address; /// Errors during serialization/deserialization. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/ix/ixon/expr.rs b/crates/ixon/src/expr.rs similarity index 98% rename from src/ix/ixon/expr.rs rename to crates/ixon/src/expr.rs index 5a6f6267..815ed69c 100644 --- a/src/ix/ixon/expr.rs +++ b/crates/ixon/src/expr.rs @@ -145,10 +145,11 @@ impl Expr { #[cfg(test)] pub mod tests { use super::*; - use crate::ix::ixon::constant::Constant; - use crate::ix::ixon::serialize::{get_expr, put_expr}; - use crate::ix::ixon::tests::gen_range; + use crate::constant::Constant; + use crate::serialize::{get_expr, put_expr}; + use crate::tests::gen_range; use quickcheck::{Arbitrary, Gen}; + use quickcheck_macros::quickcheck; use std::ptr; #[derive(Clone, Copy)] @@ -169,7 +170,7 @@ pub mod tests { /// Generate an arbitrary Expr using pointer-tree technique (no stack overflow) pub fn arbitrary_expr(g: &mut Gen) -> Arc { - use crate::ix::ixon::tests::next_case; + use crate::tests::next_case; let mut root = Expr::Var(0); let mut stack = vec![&mut root as *mut Expr]; diff --git a/src/ix/ixon/lazy.rs b/crates/ixon/src/lazy.rs similarity index 96% rename from src/ix/ixon/lazy.rs rename to crates/ixon/src/lazy.rs index 269a82eb..f08330e1 100644 --- a/src/ix/ixon/lazy.rs +++ b/crates/ixon/src/lazy.rs @@ -45,7 +45,7 @@ use std::sync::Arc; use memmap2::Mmap; -use crate::ix::address::Address; +use ix_common::address::Address; use super::constant::{Constant, ConstantInfo}; @@ -246,9 +246,9 @@ impl Eq for LazyConstant {} #[cfg(test)] mod tests { use super::*; - use crate::ix::env::DefinitionSafety; - use crate::ix::ixon::constant::{Axiom, ConstantInfo, DefKind, Definition}; - use crate::ix::ixon::expr::Expr; + use crate::constant::{Axiom, ConstantInfo, DefKind, Definition}; + use crate::expr::Expr; + use ix_common::env::DefinitionSafety; fn axiom_constant() -> Constant { Constant::new(ConstantInfo::Axio(Axiom { @@ -391,7 +391,7 @@ mod tests { /// roundtrip it through `Constant::put`/`Constant::get` for the /// `peek_variant` Muts test. fn muts_constant() -> Constant { - use crate::ix::ixon::constant::{ConstantInfo, MutConst}; + use crate::constant::{ConstantInfo, MutConst}; let m1 = MutConst::Defn(Definition { kind: DefKind::Definition, safety: DefinitionSafety::Safe, @@ -431,8 +431,8 @@ mod tests { #[test] fn peek_variant_quot() { - use crate::ix::env::QuotKind; - use crate::ix::ixon::constant::{ConstantInfo, Quotient}; + use crate::constant::{ConstantInfo, Quotient}; + use ix_common::env::QuotKind; let q = Constant::new(ConstantInfo::Quot(Quotient { kind: QuotKind::Type, lvls: 1, @@ -443,7 +443,7 @@ mod tests { #[test] fn peek_variant_dprj() { - use crate::ix::ixon::constant::{ConstantInfo, DefinitionProj}; + use crate::constant::{ConstantInfo, DefinitionProj}; let p = Constant::new(ConstantInfo::DPrj(DefinitionProj { idx: 0, block: Address::hash(b"some-block"), @@ -453,7 +453,7 @@ mod tests { #[test] fn peek_variant_iprj() { - use crate::ix::ixon::constant::{ConstantInfo, InductiveProj}; + use crate::constant::{ConstantInfo, InductiveProj}; let p = Constant::new(ConstantInfo::IPrj(InductiveProj { idx: 0, block: Address::hash(b"some-block"), @@ -463,7 +463,7 @@ mod tests { #[test] fn peek_variant_rprj() { - use crate::ix::ixon::constant::{ConstantInfo, RecursorProj}; + use crate::constant::{ConstantInfo, RecursorProj}; let p = Constant::new(ConstantInfo::RPrj(RecursorProj { idx: 0, block: Address::hash(b"some-block"), @@ -473,7 +473,7 @@ mod tests { #[test] fn peek_variant_cprj() { - use crate::ix::ixon::constant::{ConstantInfo, ConstructorProj}; + use crate::constant::{ConstantInfo, ConstructorProj}; let p = Constant::new(ConstantInfo::CPrj(ConstructorProj { idx: 0, cidx: 0, diff --git a/src/ix/ixon.rs b/crates/ixon/src/lib.rs similarity index 98% rename from src/ix/ixon.rs rename to crates/ixon/src/lib.rs index 5c540514..84a13add 100644 --- a/src/ix/ixon.rs +++ b/crates/ixon/src/lib.rs @@ -13,6 +13,7 @@ pub mod env; pub mod error; pub mod expr; pub mod lazy; +pub mod map; pub mod merkle; pub mod metadata; pub mod proof; @@ -86,7 +87,7 @@ pub mod tests { #[cfg(test)] mod doc_examples { use super::*; - use crate::ix::address::Address; + use ix_common::address::Address; // ========================================================================= // Tag4 examples (docs section "Tag4 (4-bit flag)") @@ -373,8 +374,8 @@ mod doc_examples { fn definition_packed_kind_safety() { // DefKind::Definition = 0, DefinitionSafety::Safe = 1 // Packed: (0 << 2) | 1 = 0x01 - use crate::ix::env::DefinitionSafety; use constant::{DefKind, Definition}; + use ix_common::env::DefinitionSafety; let def = Definition { kind: DefKind::Definition, @@ -392,8 +393,8 @@ mod doc_examples { fn definition_opaque_unsafe() { // DefKind::Opaque = 1, DefinitionSafety::Unsafe = 0 // Packed: (1 << 2) | 0 = 0x04 - use crate::ix::env::DefinitionSafety; use constant::{DefKind, Definition}; + use ix_common::env::DefinitionSafety; let def = Definition { kind: DefKind::Opaque, @@ -411,8 +412,8 @@ mod doc_examples { fn definition_theorem_partial() { // DefKind::Theorem = 2, DefinitionSafety::Partial = 2 // Packed: (2 << 2) | 2 = 0x0A - use crate::ix::env::DefinitionSafety; use constant::{DefKind, Definition}; + use ix_common::env::DefinitionSafety; let def = Definition { kind: DefKind::Theorem, @@ -433,8 +434,8 @@ mod doc_examples { #[test] fn constant_defn_tag() { // Constant with Defn -> Tag4 { flag: 0xD, size: 0 } -> 0xD0 - use crate::ix::env::DefinitionSafety; use constant::{Constant, ConstantInfo, DefKind, Definition}; + use ix_common::env::DefinitionSafety; let constant = Constant::new(ConstantInfo::Defn(Definition { kind: DefKind::Definition, @@ -451,8 +452,8 @@ mod doc_examples { #[test] fn constant_muts_tag() { // Muts with 3 entries -> Tag4 { flag: 0xC, size: 3 } -> 0xC3 - use crate::ix::env::DefinitionSafety; use constant::{Constant, ConstantInfo, DefKind, Definition, MutConst}; + use ix_common::env::DefinitionSafety; let def = Definition { kind: DefKind::Definition, diff --git a/crates/ixon/src/map.rs b/crates/ixon/src/map.rs new file mode 100644 index 00000000..748ebafb --- /dev/null +++ b/crates/ixon/src/map.rs @@ -0,0 +1,101 @@ +//! Map type used by `Env`. +//! +//! On host, this is `dashmap::DashMap` — concurrent reads/writes for the +//! parallel ingress path. On `riscv64`, `DashMap` pulls in `parking_lot_core`, +//! whose `HashTable::new` calls `Instant::now()` (unsupported in the Zisk +//! guest's stdlib). Instead, alias to a thin single-threaded wrapper around +//! `rustc_hash::FxHashMap` that mirrors the subset of DashMap's API used here. + +#[cfg(not(target_arch = "riscv64"))] +pub use dashmap::DashMap as IxonMap; + +#[cfg(target_arch = "riscv64")] +pub use riscv_impl::IxonMap; + +#[cfg(target_arch = "riscv64")] +mod riscv_impl { + use std::collections::hash_map; + use std::hash::Hash; + use std::ops::Deref; + + use rustc_hash::FxHashMap; + + #[derive(Debug)] + pub struct IxonMap(FxHashMap); + + impl Default for IxonMap { + fn default() -> Self { + Self(FxHashMap::default()) + } + } + + impl IxonMap { + pub fn new() -> Self { + Self::default() + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + pub fn contains_key(&self, k: &K) -> bool { + self.0.contains_key(k) + } + + pub fn insert(&mut self, k: K, v: V) -> Option { + self.0.insert(k, v) + } + + pub fn clear(&mut self) { + self.0.clear(); + } + + pub fn get(&self, k: &K) -> Option> { + self.0.get_key_value(k).map(|(k, v)| MapRef { k, v }) + } + + pub fn get_mut(&mut self, k: &K) -> Option<&mut V> { + self.0.get_mut(k) + } + + pub fn iter(&self) -> Iter<'_, K, V> { + Iter(self.0.iter()) + } + } + + /// Read guard exposing DashMap's `key()` / `value()` shape. + pub struct MapRef<'a, K, V> { + k: &'a K, + v: &'a V, + } + + impl<'a, K, V> MapRef<'a, K, V> { + pub fn key(&self) -> &K { + self.k + } + + pub fn value(&self) -> &V { + self.v + } + } + + impl<'a, K, V> Deref for MapRef<'a, K, V> { + type Target = V; + fn deref(&self) -> &V { + self.v + } + } + + pub struct Iter<'a, K, V>(hash_map::Iter<'a, K, V>); + + impl<'a, K, V> Iterator for Iter<'a, K, V> { + type Item = MapRef<'a, K, V>; + fn next(&mut self) -> Option { + self.0.next().map(|(k, v)| MapRef { k, v }) + } + } +} diff --git a/src/ix/ixon/merkle.rs b/crates/ixon/src/merkle.rs similarity index 99% rename from src/ix/ixon/merkle.rs rename to crates/ixon/src/merkle.rs index 081f89e9..78505f29 100644 --- a/src/ix/ixon/merkle.rs +++ b/crates/ixon/src/merkle.rs @@ -30,7 +30,7 @@ //! introduces CVE-2012-2459-style malleability where two distinct leaf //! lists can produce the same root. -use crate::ix::address::Address; +use ix_common::address::Address; /// Domain-separation prefix for leaf hashes. pub const LEAF_DOMAIN: u8 = 0x00; @@ -197,6 +197,7 @@ pub fn verify_merkle_proof( mod tests { use super::*; use quickcheck::{Arbitrary, Gen}; + use quickcheck_macros::quickcheck; fn addr(seed: &[u8]) -> Address { Address::hash(seed) diff --git a/src/ix/ixon/metadata.rs b/crates/ixon/src/metadata.rs similarity index 96% rename from src/ix/ixon/metadata.rs rename to crates/ixon/src/metadata.rs index e6f48db1..c8f16d2c 100644 --- a/src/ix/ixon/metadata.rs +++ b/crates/ixon/src/metadata.rs @@ -12,8 +12,8 @@ use std::collections::HashMap; use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::env::{self, BinderInfo, Name, ReducibilityHints}; +use ix_common::address::Address; +use ix_common::env::{self, BinderInfo, Name, ReducibilityHints}; use super::env::AuxLayout; use super::expr::Expr; @@ -330,7 +330,7 @@ pub fn resolve_kvmap( }, DataValue::OfNat(a) => { let bytes = ixon_env.get_blob(a)?; - env::DataValue::OfNat(lean_ffi::nat::Nat::from_le_bytes(&bytes)) + env::DataValue::OfNat(bignat::Nat::from_le_bytes(&bytes)) }, DataValue::OfInt(a) => { let bytes = ixon_env.get_blob(a)?; @@ -389,8 +389,8 @@ fn deser_addr(buf: &mut &[u8]) -> Option
{ fn deser_int(bytes: &[u8]) -> Option { let (&tag, rest) = bytes.split_first()?; match tag { - 0 => Some(env::Int::OfNat(lean_ffi::nat::Nat::from_le_bytes(rest))), - 1 => Some(env::Int::NegSucc(lean_ffi::nat::Nat::from_le_bytes(rest))), + 0 => Some(env::Int::OfNat(bignat::Nat::from_le_bytes(rest))), + 1 => Some(env::Int::NegSucc(bignat::Nat::from_le_bytes(rest))), _ => None, } } @@ -401,8 +401,8 @@ fn deser_substring( ) -> Option { let str_addr = deser_addr(buf)?; let s = String::from_utf8(ixon_env.get_blob(&str_addr)?).ok()?; - let start_pos = lean_ffi::nat::Nat::from(deser_tag0(buf)?); - let stop_pos = lean_ffi::nat::Nat::from(deser_tag0(buf)?); + let start_pos = bignat::Nat::from(deser_tag0(buf)?); + let stop_pos = bignat::Nat::from(deser_tag0(buf)?); Some(env::Substring { str: s, start_pos, stop_pos }) } @@ -413,9 +413,9 @@ fn deser_source_info( match deser_u8(buf)? { 0 => { let leading = deser_substring(buf, ixon_env)?; - let leading_pos = lean_ffi::nat::Nat::from(deser_tag0(buf)?); + let leading_pos = bignat::Nat::from(deser_tag0(buf)?); let trailing = deser_substring(buf, ixon_env)?; - let trailing_pos = lean_ffi::nat::Nat::from(deser_tag0(buf)?); + let trailing_pos = bignat::Nat::from(deser_tag0(buf)?); Some(env::SourceInfo::Original( leading, leading_pos, @@ -424,8 +424,8 @@ fn deser_source_info( )) }, 1 => { - let start = lean_ffi::nat::Nat::from(deser_tag0(buf)?); - let end = lean_ffi::nat::Nat::from(deser_tag0(buf)?); + let start = bignat::Nat::from(deser_tag0(buf)?); + let end = bignat::Nat::from(deser_tag0(buf)?); let canonical = deser_u8(buf)? != 0; Some(env::SourceInfo::Synthetic(start, end, canonical)) }, @@ -560,8 +560,15 @@ pub(super) fn get_vec_len(buf: &mut &[u8]) -> Result { // BinderInfo and ReducibilityHints serialization // =========================================================================== -impl BinderInfo { - pub fn put(&self, buf: &mut Vec) { +/// Extension trait for serializing/deserializing small env-side enums whose +/// types live in `ix-types` (so we can't define inherent impls here). +pub trait IxonByteSerde: Sized { + fn put_ser(&self, buf: &mut Vec); + fn get_ser(buf: &mut &[u8]) -> Result; +} + +impl IxonByteSerde for BinderInfo { + fn put_ser(&self, buf: &mut Vec) { match self { Self::Default => put_u8(0, buf), Self::Implicit => put_u8(1, buf), @@ -570,7 +577,7 @@ impl BinderInfo { } } - pub fn get_ser(buf: &mut &[u8]) -> Result { + fn get_ser(buf: &mut &[u8]) -> Result { match get_u8(buf)? { 0 => Ok(Self::Default), 1 => Ok(Self::Implicit), @@ -581,8 +588,8 @@ impl BinderInfo { } } -impl ReducibilityHints { - pub fn put(&self, buf: &mut Vec) { +impl IxonByteSerde for ReducibilityHints { + fn put_ser(&self, buf: &mut Vec) { match self { Self::Opaque => put_u8(0, buf), Self::Abbrev => put_u8(1, buf), @@ -593,7 +600,7 @@ impl ReducibilityHints { } } - pub fn get_ser(buf: &mut &[u8]) -> Result { + fn get_ser(buf: &mut &[u8]) -> Result { match get_u8(buf)? { 0 => Ok(Self::Opaque), 1 => Ok(Self::Abbrev), @@ -1004,7 +1011,7 @@ impl ConstantMetaInfo { put_u8(0, buf); put_idx(name, idx, buf)?; put_idx_vec(lvls, idx, buf)?; - hints.put(buf); + hints.put_ser(buf); put_idx_vec(all, idx, buf)?; put_idx_vec(ctx, idx, buf)?; arena.put_indexed(idx, buf)?; @@ -1182,28 +1189,6 @@ impl ConstantMetaInfo { #[cfg(test)] mod tests { use super::*; - use quickcheck::{Arbitrary, Gen}; - - impl Arbitrary for BinderInfo { - fn arbitrary(g: &mut Gen) -> Self { - match u8::arbitrary(g) % 4 { - 0 => Self::Default, - 1 => Self::Implicit, - 2 => Self::StrictImplicit, - _ => Self::InstImplicit, - } - } - } - - impl Arbitrary for ReducibilityHints { - fn arbitrary(g: &mut Gen) -> Self { - match u8::arbitrary(g) % 3 { - 0 => Self::Opaque, - 1 => Self::Abbrev, - _ => Self::Regular(u32::arbitrary(g)), - } - } - } #[test] fn test_binder_info_roundtrip() { @@ -1214,7 +1199,7 @@ mod tests { BinderInfo::InstImplicit, ] { let mut buf = Vec::new(); - bi.put(&mut buf); + bi.put_ser(&mut buf); assert_eq!(BinderInfo::get_ser(&mut buf.as_slice()).unwrap(), bi); } } @@ -1227,7 +1212,7 @@ mod tests { ReducibilityHints::Regular(42), ] { let mut buf = Vec::new(); - h.put(&mut buf); + h.put_ser(&mut buf); assert_eq!(ReducibilityHints::get_ser(&mut buf.as_slice()).unwrap(), h); } } diff --git a/src/ix/ixon/proof.rs b/crates/ixon/src/proof.rs similarity index 99% rename from src/ix/ixon/proof.rs rename to crates/ixon/src/proof.rs index 805f0017..94fc2b6e 100644 --- a/src/ix/ixon/proof.rs +++ b/crates/ixon/src/proof.rs @@ -8,8 +8,8 @@ //! order. This enables revealing specific fields of a committed constant without //! exposing the full structure. -use crate::ix::address::Address; -use crate::ix::env::{DefinitionSafety, QuotKind}; +use ix_common::address::Address; +use ix_common::env::{DefinitionSafety, QuotKind}; use super::constant::DefKind; use super::tag::{Tag0, Tag4}; @@ -144,7 +144,7 @@ pub enum RevealConstantInfo { /// Orthogonal to typechecking; carries no assumptions. /// - **Contains**: structural membership claim — `const_addr` is a leaf /// in the merkle tree rooted at `tree`. Used by the aggregation -/// circuit to discharge a leaf from a conditional claim's assumption +/// circuit to resolve a leaf from a conditional claim's assumption /// set. Carries no assumptions itself. /// /// The `assumptions` root may be any merkle tree (canonical sorted+ @@ -1176,6 +1176,7 @@ impl Proof { mod tests { use super::*; use quickcheck::{Arbitrary, Gen}; + use quickcheck_macros::quickcheck; // ========== Arbitrary impls ========== diff --git a/src/ix/ixon/serialize.rs b/crates/ixon/src/serialize.rs similarity index 94% rename from src/ix/ixon/serialize.rs rename to crates/ixon/src/serialize.rs index ecbed0bf..f98c9a2a 100644 --- a/src/ix/ixon/serialize.rs +++ b/crates/ixon/src/serialize.rs @@ -9,8 +9,8 @@ use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::env::{DefinitionSafety, QuotKind}; +use ix_common::address::Address; +use ix_common::env::{DefinitionSafety, QuotKind, ReducibilityHints}; use super::constant::{ Axiom, Constant, ConstantInfo, Constructor, ConstructorProj, DefKind, @@ -18,6 +18,7 @@ use super::constant::{ Recursor, RecursorProj, RecursorRule, }; use super::expr::Expr; +use super::metadata::IxonByteSerde; use super::tag::{Tag0, Tag4}; use super::univ::{Univ, get_univ, put_univ}; @@ -75,6 +76,24 @@ fn put_address(a: &Address, buf: &mut Vec) { put_bytes(a.as_bytes(), buf); } +/// Read the optional trailing `anon_hints` section written by `Env::put`. +/// No-op when no bytes remain after the comms section — backward-compatible +/// with `.ixe` that have no hints or predate the section. Inserts into +/// `env.anon_hints` (overwriting any value harvested from a Named section, +/// with the identical value, so the order of harvest vs. section is moot). +fn read_anon_hints_section(buf: &mut &[u8], env: &mut Env) -> Result<(), String> { + if buf.is_empty() { + return Ok(()); + } + let n = get_u64(buf)?; + for _ in 0..n { + let addr = get_address(buf)?; + let hints = ReducibilityHints::get_ser(buf)?; + env.anon_hints.insert(addr, hints); + } + Ok(()) +} + fn get_address(buf: &mut &[u8]) -> Result { if buf.len() < 32 { return Err(format!("get_address: need 32 bytes, have {}", buf.len())); @@ -425,28 +444,26 @@ impl DefKind { } } -impl DefinitionSafety { - fn to_u8(self) -> u8 { - match self { - Self::Unsafe => 0, - Self::Safe => 1, - Self::Partial => 2, - } +fn definition_safety_to_u8(s: DefinitionSafety) -> u8 { + match s { + DefinitionSafety::Unsafe => 0, + DefinitionSafety::Safe => 1, + DefinitionSafety::Partial => 2, } +} - fn from_u8(x: u8) -> Result { - match x { - 0 => Ok(Self::Unsafe), - 1 => Ok(Self::Safe), - 2 => Ok(Self::Partial), - x => Err(format!("DefinitionSafety::from_u8: invalid {x}")), - } +fn definition_safety_from_u8(x: u8) -> Result { + match x { + 0 => Ok(DefinitionSafety::Unsafe), + 1 => Ok(DefinitionSafety::Safe), + 2 => Ok(DefinitionSafety::Partial), + x => Err(format!("DefinitionSafety::from_u8: invalid {x}")), } } /// Pack DefKind (2 bits) and DefinitionSafety (2 bits) into a single byte. fn pack_def_kind_safety(kind: DefKind, safety: DefinitionSafety) -> u8 { - (kind.to_u8() << 2) | safety.to_u8() + (kind.to_u8() << 2) | definition_safety_to_u8(safety) } /// Unpack DefKind and DefinitionSafety from a single byte. @@ -454,12 +471,12 @@ fn unpack_def_kind_safety( b: u8, ) -> Result<(DefKind, DefinitionSafety), String> { let kind = DefKind::from_u8(b >> 2)?; - let safety = DefinitionSafety::from_u8(b & 0x3)?; + let safety = definition_safety_from_u8(b & 0x3)?; Ok((kind, safety)) } -impl QuotKind { - pub fn put_ser(&self, buf: &mut Vec) { +impl IxonByteSerde for QuotKind { + fn put_ser(&self, buf: &mut Vec) { match self { Self::Type => put_u8(0, buf), Self::Ctor => put_u8(1, buf), @@ -468,7 +485,7 @@ impl QuotKind { } } - pub fn get_ser(buf: &mut &[u8]) -> Result { + fn get_ser(buf: &mut &[u8]) -> Result { match get_u8(buf)? { 0 => Ok(Self::Type), 1 => Ok(Self::Ctor), @@ -870,8 +887,8 @@ impl Constant { // Name serialization // ============================================================================ -use crate::ix::env::{Name, NameData}; -use lean_ffi::nat::Nat; +use bignat::Nat; +use ix_common::env::{Name, NameData}; use rustc_hash::FxHashMap; /// Serialize a Name to bytes (full recursive serialization, for standalone use). @@ -1109,6 +1126,7 @@ impl Env { /// insertion orders), and DashMap iteration order is shard-dependent. /// Sorting the keys is the minimum work to guarantee that. pub fn put(&self, buf: &mut Vec) -> Result<(), String> { + #[cfg(not(target_arch = "riscv64"))] use rayon::slice::ParallelSliceMut; // Chatty per-section logging gated on IX_QUIET=1 (disables) so we can @@ -1131,7 +1149,10 @@ impl Env { // ───────────────────────────────────────────────────────────────────── let mut const_addrs: Vec
= self.consts.iter().map(|e| e.key().clone()).collect(); + #[cfg(not(target_arch = "riscv64"))] const_addrs.par_sort_unstable(); + #[cfg(target_arch = "riscv64")] + const_addrs.sort_unstable(); let root = merkle_root_canonical(&const_addrs).unwrap_or_else(zero_address); put_address(&root, buf); @@ -1144,7 +1165,10 @@ impl Env { } let mut blob_addrs: Vec
= self.blobs.iter().map(|e| e.key().clone()).collect(); + #[cfg(not(target_arch = "riscv64"))] blob_addrs.par_sort_unstable(); + #[cfg(target_arch = "riscv64")] + blob_addrs.sort_unstable(); put_u64(blob_addrs.len() as u64, buf); for addr in &blob_addrs { if let Some(entry) = self.blobs.get(addr) { @@ -1260,9 +1284,14 @@ impl Env { // Sort by the cached name hash bytes (same key used by every existing // Section 4 ordering guarantee). `par_sort_unstable_by` uses rayon to // parallelize the compare across all cores. + #[cfg(not(target_arch = "riscv64"))] named_keys.par_sort_unstable_by(|a, b| { a.get_hash().as_bytes().cmp(b.get_hash().as_bytes()) }); + #[cfg(target_arch = "riscv64")] + named_keys.sort_unstable_by(|a, b| { + a.get_hash().as_bytes().cmp(b.get_hash().as_bytes()) + }); if !quiet { eprintln!( "[Env::put] section 4/5 named: collected+sorted in {:.1}s, \ @@ -1297,7 +1326,10 @@ impl Env { } let mut comm_addrs: Vec
= self.comms.iter().map(|e| e.key().clone()).collect(); + #[cfg(not(target_arch = "riscv64"))] comm_addrs.par_sort_unstable(); + #[cfg(target_arch = "riscv64")] + comm_addrs.sort_unstable(); put_u64(comm_addrs.len() as u64, buf); for addr in &comm_addrs { if let Some(entry) = self.comms.get(addr) { @@ -1311,6 +1343,29 @@ impl Env { sec_start.elapsed().as_secs_f64(), buf.len(), ); + } + + // Optional trailing section: anon_hints (Address -> ReducibilityHints). + // `get_anon` normally HARVESTS hints from the Named section; a closure + // sub-env (built for shard injection) DROPS that section, which would + // force the kernel to `Regular(0)` and add a def-eq overhead vs whole-env + // proving. Carrying the hints here lets the guest reproduce vanilla kernel + // behavior exactly. Written only when populated, so compiler-produced + // `.ixe` (empty map) are byte-identical to before; loaders read it only if + // bytes remain after comms. Hints are performance-only (the `Regular(0)` + // fallback is always correct), so this section is intentionally NOT covered + // by the consts merkle root. + if !self.anon_hints.is_empty() { + let mut hint_addrs: Vec
= self.anon_hints.keys().cloned().collect(); + hint_addrs.sort_unstable(); + put_u64(hint_addrs.len() as u64, buf); + for addr in &hint_addrs { + put_address(addr, buf); + self.anon_hints[addr].put_ser(buf); + } + } + + if !quiet { eprintln!( "[Env::put] ALL DONE: {} bytes in {:.1}s", buf.len(), @@ -1343,7 +1398,8 @@ impl Env { // recomputed value at the end of deserialization. let stored_root = get_address(buf)?; - let env = Env::new(); + #[cfg_attr(not(target_arch = "riscv64"), allow(unused_mut))] + let mut env = Env::new(); // Section 1: Blobs let num_blobs = get_u64(buf)?; @@ -1390,7 +1446,9 @@ impl Env { addr.hex() )); } - env.store_const_lazy(addr, bytes.into()); + env + .consts + .insert(addr, crate::lazy::LazyConstant::from_bytes(bytes.into())); } // Section 3: Names (build lookup table and reverse index for metadata) @@ -1431,6 +1489,9 @@ impl Env { env.comms.insert(addr, comm); } + // Optional trailing anon_hints section (see `Env::put`). + read_anon_hints_section(buf, &mut env)?; + // Verify the stored merkle root matches what we'd compute from // env.consts. Empty const set → expected = zero_address(). // Rejects any tampering with the header. @@ -1528,7 +1589,9 @@ impl Env { addr.hex() )); } - env.store_const_lazy(addr, bytes.into()); + env + .consts + .insert(addr, crate::lazy::LazyConstant::from_bytes(bytes.into())); } // Section 3: Names — parse and DISCARD. We still need a populated @@ -1573,6 +1636,11 @@ impl Env { let _comm = Comm::get(buf)?; } + // Optional trailing anon_hints section (see `Env::put`). For a closure + // sub-env this carries the hints the dropped Named section would have, so + // the kernel reproduces vanilla behavior with no def-eq overhead. + read_anon_hints_section(buf, &mut env)?; + drop(names_lookup); drop(name_reverse_index); @@ -1613,6 +1681,7 @@ impl Env { /// On Linux, the kernel's adaptive readahead handles the linear /// scan during section parsing efficiently; subsequent random /// access from worker kernel-check threads pages in as needed. + #[cfg(not(target_arch = "riscv64"))] pub fn get_anon_mmap(path: &std::path::Path) -> Result { let file = std::fs::File::open(path).map_err(|e| { format!("Env::get_anon_mmap: open {}: {e}", path.display()) @@ -1723,7 +1792,14 @@ impl Env { addr.hex() )); } - env.store_const_lazy_mmap(addr, Arc::clone(&mmap), offset, len); + env.consts.insert( + addr, + crate::lazy::LazyConstant::from_mmap_slice( + Arc::clone(&mmap), + offset, + len, + ), + ); buf = &buf[len..]; } @@ -1763,6 +1839,9 @@ impl Env { let _comm = Comm::get(&mut buf)?; } + // Optional trailing anon_hints section (see `Env::put`). + read_anon_hints_section(&mut buf, &mut env)?; + drop(names_lookup); drop(name_reverse_index); @@ -1882,8 +1961,9 @@ impl Env { /// Mathlib because 4.7M shard-lock acquisitions dominate vs the one-time /// ~150 MB tuple-clone allocation. fn topological_sort_names( - names: &dashmap::DashMap, + names: &crate::map::IxonMap, ) -> Vec<(Address, Name)> { + #[cfg(not(target_arch = "riscv64"))] use rayon::slice::ParallelSliceMut; use rustc_hash::FxHashSet; @@ -1922,7 +2002,10 @@ fn topological_sort_names( // during DFS). Parallel sort uses rayon over address bytes. let mut sorted_entries: Vec<(Address, Name)> = names.iter().map(|e| (e.key().clone(), e.value().clone())).collect(); + #[cfg(not(target_arch = "riscv64"))] sorted_entries.par_sort_unstable_by(|a, b| a.0.cmp(&b.0)); + #[cfg(target_arch = "riscv64")] + sorted_entries.sort_unstable_by(|a, b| a.0.cmp(&b.0)); for (_, name) in &sorted_entries { visit(name, &mut visited, &mut result); } @@ -1933,9 +2016,10 @@ fn topological_sort_names( #[cfg(test)] mod tests { use super::*; - use crate::ix::ixon::constant::tests::gen_constant; - use crate::ix::ixon::tests::gen_range; + use crate::constant::tests::gen_constant; + use crate::tests::gen_range; use quickcheck::{Arbitrary, Gen}; + use quickcheck_macros::quickcheck; #[quickcheck] fn prop_pack_bools_roundtrip(x: Vec) -> bool { @@ -2215,8 +2299,8 @@ mod tests { } fn defn_const_discriminator(refs: Vec
, lvls: u64) -> Constant { - use crate::ix::env::DefinitionSafety; - use crate::ix::ixon::constant::{DefKind, Definition}; + use ix_common::env::DefinitionSafety; + use crate::constant::{DefKind, Definition}; Constant::with_tables( ConstantInfo::Defn(Definition { kind: DefKind::Definition, @@ -2251,7 +2335,7 @@ mod tests { #[test] fn env_root_empty_env_is_zero_address() { - use crate::ix::ixon::merkle::zero_address; + use crate::merkle::zero_address; let env = Env::new(); let mut buf = Vec::new(); env.put(&mut buf).unwrap(); @@ -2265,7 +2349,7 @@ mod tests { #[test] fn env_root_present_when_consts_nonempty() { - use crate::ix::ixon::merkle::zero_address; + use crate::merkle::zero_address; let env = Env::new(); env.store_const(Address::hash(b"a"), defn_const(vec![])); let mut buf = Vec::new(); @@ -2403,7 +2487,7 @@ mod tests { #[test] fn get_anon_keeps_consts_drops_metadata() { - use crate::ix::ixon::env::Named; + use crate::env::Named; let env = Env::new(); // Round-trip tests must use canonical addresses (see store_canonical // helper); `Env::get`/`get_anon` reject entries whose bytes don't diff --git a/src/ix/ixon/sharing.rs b/crates/ixon/src/sharing.rs similarity index 99% rename from src/ix/ixon/sharing.rs rename to crates/ixon/src/sharing.rs index 610d07c2..ccf87dd2 100644 --- a/src/ix/ixon/sharing.rs +++ b/crates/ixon/src/sharing.rs @@ -1060,7 +1060,7 @@ mod tests { #[test] fn test_roundtrip_with_sharing() { - use crate::ix::ixon::serialize::{get_expr, put_expr}; + use crate::serialize::{get_expr, put_expr}; // Create a simple expression with potential sharing let var0 = Expr::var(0); diff --git a/src/ix/ixon/tag.rs b/crates/ixon/src/tag.rs similarity index 99% rename from src/ix/ixon/tag.rs rename to crates/ixon/src/tag.rs index 240d9688..35465aaa 100644 --- a/src/ix/ixon/tag.rs +++ b/crates/ixon/src/tag.rs @@ -225,6 +225,7 @@ impl Tag0 { mod tests { use super::*; use quickcheck::{Arbitrary, Gen}; + use quickcheck_macros::quickcheck; // ============================================================================ // Arbitrary implementations diff --git a/src/ix/ixon/univ.rs b/crates/ixon/src/univ.rs similarity index 98% rename from src/ix/ixon/univ.rs rename to crates/ixon/src/univ.rs index ce3e9db8..41282332 100644 --- a/src/ix/ixon/univ.rs +++ b/crates/ixon/src/univ.rs @@ -162,8 +162,9 @@ pub fn get_univ(buf: &mut &[u8]) -> Result, String> { #[cfg(test)] pub mod tests { use super::*; - use crate::ix::ixon::tests::{gen_range, next_case}; + use crate::tests::{gen_range, next_case}; use quickcheck::{Arbitrary, Gen}; + use quickcheck_macros::quickcheck; use std::ptr; #[derive(Clone, Copy)] diff --git a/crates/kernel/Cargo.toml b/crates/kernel/Cargo.toml new file mode 100644 index 00000000..996eab3e --- /dev/null +++ b/crates/kernel/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "ix-kernel" +version.workspace = true +edition.workspace = true +license.workspace = true + +[dependencies] +bignat = { workspace = true } +blake3 = { workspace = true } +dashmap = { workspace = true } +indexmap = { workspace = true } +ix-common = { workspace = true } +ixon = { workspace = true } +itertools = { workspace = true } +log = { workspace = true } +num-bigint = { workspace = true } +rustc-hash = { workspace = true } + +[target.'cfg(not(target_arch = "riscv64"))'.dependencies] +dashmap = { workspace = true, features = ["rayon"] } +rayon = { workspace = true } + +[dev-dependencies] +# `examples/perf_check.rs` initializes a logger so the `KEnv::Drop` perf +# summary (emitted via `log::info!` when `IX_PERF_COUNTERS=1`) actually +# reaches stderr. Dev-only — production builds never pull this in. +env_logger = "0.11" +quickcheck = { workspace = true } +quickcheck_macros = { workspace = true } + +# Native rerun of the SP1/Zisk guest `check_const` loop. The zkVM build +# disables `IX_*` env vars (`src/lib.rs::env_var_os`), so the perf-counter +# / fuel summary in `src/perf.rs` is only observable through this binary. +# See the example's module doc for the intended workflow. +[[example]] +name = "perf_check" +path = "examples/perf_check.rs" + +[lints] +workspace = true diff --git a/crates/kernel/examples/block_reduce_histo.rs b/crates/kernel/examples/block_reduce_histo.rs new file mode 100644 index 00000000..dd0045a3 --- /dev/null +++ b/crates/kernel/examples/block_reduce_histo.rs @@ -0,0 +1,117 @@ +//! Check a single named constant's block and dump per-constant reduction +//! histograms: which constants the kernel delta-unfolds, which recursors +//! fire iota, and how many `Nat.succ` peels happen. Reverse-maps addresses +//! to Lean names via the env's `named` metadata. +//! +//! IX_REDUCE_HISTO=1 cargo run -p ix-kernel --release \ +//! --example block_reduce_histo -- [top_k] + +use std::sync::atomic::Ordering; + +use ix_common::address::Address; +use ix_kernel::anon_work::build_anon_work; +use ix_kernel::env::KEnv; +use ix_kernel::id::KId; +use ix_kernel::mode::Anon; +use ix_kernel::tc::TypeChecker; +use ixon::constant::ConstantInfo as CI; +use ixon::env::Env as IxonEnv; + +/// A constant's home block: a projection's `block`, else the constant itself. +fn block_of(env: &IxonEnv, addr: &Address) -> Address { + match env.get_const(addr) { + Some(c) => match &c.info { + CI::IPrj(p) => p.block.clone(), + CI::CPrj(p) => p.block.clone(), + CI::RPrj(p) => p.block.clone(), + CI::DPrj(p) => p.block.clone(), + _ => addr.clone(), + }, + None => addr.clone(), + } +} + +fn main() { + let args: Vec = std::env::args().collect(); + let (Some(path), Some(target)) = (args.get(1).cloned(), args.get(2).cloned()) + else { + eprintln!("usage: block_reduce_histo [top_k]"); + std::process::exit(1); + }; + let top_k: usize = args.get(3).and_then(|s| s.parse().ok()).unwrap_or(40); + + if std::env::var_os("IX_REDUCE_HISTO").is_none() { + eprintln!("warning: IX_REDUCE_HISTO is not set; histograms will be empty"); + } + + let bytes = std::fs::read(&path).expect("read .ixe"); + let full = IxonEnv::get(&mut &bytes[..]).expect("get"); + + // Resolve the Lean name to its anon addr, then its home block. + let Some(target_addr) = full + .named + .iter() + .find(|e| e.key().to_string() == target) + .map(|e| e.value().addr.clone()) + else { + eprintln!("name not found in env: {target}"); + std::process::exit(1); + }; + let target_block = block_of(&full, &target_addr); + eprintln!( + "target {target} addr={}… block={}…", + &target_addr.hex()[..16], + &target_block.hex()[..16] + ); + + // Find the anon work item for that block and check just that item. + let env = IxonEnv::get_anon(&mut &bytes[..]).expect("get_anon"); + let work = build_anon_work(&env).expect("build_anon_work"); + let item = work + .iter() + .find(|item| block_of(&env, item.primary()) == target_block) + .expect("no work item for target block"); + + let mut kenv = KEnv::::new(); + let start = std::time::Instant::now(); + let kid = KId::::new(item.primary().clone(), ()); + let mut tc = TypeChecker::::new_with_lazy_anon(&mut kenv, &env); + let result = tc.check_const(&kid); + let fuel = tc.fuel_used(); + eprintln!( + "check_const: {:?} in {:.1}s, fuel(heartbeats)={fuel}", + result.map(|_| "ok"), + start.elapsed().as_secs_f64() + ); + + // Reverse-map addr → Lean name (named addrs are anon addrs here). + let name_of = |addr: &Address| -> String { + full + .named + .iter() + .find(|e| e.value().addr == *addr) + .map(|e| e.key().to_string()) + .unwrap_or_else(|| format!("", &addr.hex()[..16])) + }; + + let dump = |label: &str, + histo: &dashmap::DashMap| { + let mut rows: Vec<(Address, u64)> = + histo.iter().map(|e| (e.key().clone(), *e.value())).collect(); + rows.sort_by(|a, b| b.1.cmp(&a.1)); + let total: u64 = rows.iter().map(|(_, n)| n).sum(); + eprintln!("\n== {label}: {total} total, {} distinct ==", rows.len()); + for (addr, n) in rows.iter().take(top_k) { + #[allow(clippy::cast_precision_loss)] + let pct = *n as f64 / total.max(1) as f64 * 100.0; + eprintln!(" {n:>12} ({pct:>5.1}%) {}", name_of(addr)); + } + }; + + dump("delta unfolds", &ix_kernel::perf::DELTA_HISTO); + dump("iota reductions", &ix_kernel::perf::IOTA_HISTO); + eprintln!( + "\nNat.succ peels: {}", + ix_kernel::perf::NAT_SUCC_PEELS.load(Ordering::Relaxed) + ); +} diff --git a/crates/kernel/examples/heaviest_block.rs b/crates/kernel/examples/heaviest_block.rs new file mode 100644 index 00000000..9ffdff6d --- /dev/null +++ b/crates/kernel/examples/heaviest_block.rs @@ -0,0 +1,120 @@ +//! Identify, by Lean name, the heaviest blocks in a `.ixe` — in particular the +//! atomic mutual block that floors sharding. Profiles the env (heartbeats per +//! block), ranks blocks, then reverse-maps each block's address to the Lean +//! names of its members via the env's `names` metadata. +//! +//! cargo run -p ix-kernel --release --example heaviest_block -- [top_k] + +use ix_common::address::Address; +use ix_kernel::anon_work::build_anon_work; +use ix_kernel::env::KEnv; +use ix_kernel::id::KId; +use ix_kernel::mode::Anon; +use ix_kernel::profile::{ProfileBuilder, ProfileSink}; +use ix_kernel::tc::TypeChecker; +use ixon::constant::ConstantInfo as CI; +use ixon::env::Env as IxonEnv; + +/// A constant's home block: a projection's `block`, else the constant itself. +fn block_of(env: &IxonEnv, addr: &Address) -> Address { + match env.get_const(addr) { + Some(c) => match &c.info { + CI::IPrj(p) => p.block.clone(), + CI::CPrj(p) => p.block.clone(), + CI::RPrj(p) => p.block.clone(), + CI::DPrj(p) => p.block.clone(), + _ => addr.clone(), + }, + None => addr.clone(), + } +} + +fn main() { + let args: Vec = std::env::args().collect(); + let Some(path) = args.get(1).cloned() else { + eprintln!("usage: heaviest_block [top_k]"); + std::process::exit(1); + }; + let top_k: usize = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(3); + + let bytes = std::fs::read(&path).expect("read .ixe"); + + // ---- Profile (anon) for per-block heartbeats. ---- + let env = IxonEnv::get_anon(&mut &bytes[..]).expect("get_anon"); + let work = build_anon_work(&env).expect("build_anon_work"); + let mut kenv = KEnv::::new(); + kenv.profile_sink = Some(ProfileSink::new(true)); + for item in &work { + let kid = KId::::new(item.primary().clone(), ()); + let mut tc = TypeChecker::::new_with_lazy_anon(&mut kenv, &env); + let _ = tc.check_const(&kid); + tc.finish_constant_accounting(); + } + let sink = kenv.profile_sink.take().unwrap(); + let mut builder = ProfileBuilder::new(); + for (consumer, rec) in &sink.records { + builder.block(block_of(&env, consumer), rec.fuel, 0, 1); + } + let profile = builder.finish(); + let mut blocks: Vec<(Address, u64)> = + profile.blocks().iter().map(|b| (b.addr.clone(), b.heartbeats)).collect(); + blocks.sort_by(|a, b| b.1.cmp(&a.1)); + + // ---- Full env for names; reverse-map addresses → Lean names. ---- + let full = IxonEnv::get(&mut &bytes[..]).expect("get"); + + eprintln!( + "env metadata: {} consts, {} named, {} names entries", + full.consts.iter().count(), + full.named.iter().count(), + full.names.iter().count(), + ); + // Diagnostic: is the heaviest anon block addr present in consts/names/named? + if let Some((addr, _)) = blocks.first() { + eprintln!( + "diag: heaviest anon block {}… in consts={} names={} named_addrs={}", + &addr.hex()[..16], + full.get_const(addr).is_some(), + full.names.get(addr).is_some(), + full.named.iter().any(|e| e.value().addr == *addr), + ); + } + eprintln!("diag: sample names entries (addr → name):"); + for e in full.names.iter().take(4) { + eprintln!(" {}… → {}", &e.key().hex()[..16], e.value()); + } + eprintln!("diag: sample consts keys:"); + for e in full.consts.iter().take(4) { + eprintln!(" {}…", &e.key().hex()[..16]); + } + eprintln!("Top {top_k} blocks by heartbeats in {path}:"); + for (addr, hb) in blocks.iter().take(top_k) { + let direct = full + .named + .iter() + .find(|e| e.value().addr == *addr) + .map(|e| e.key().to_string()); + let mut members: Vec = full + .named + .iter() + .filter(|e| block_of(&full, &e.value().addr) == *addr) + .map(|e| e.key().to_string()) + .collect(); + members.sort(); + members.dedup(); + eprintln!( + "\n {hb} heartbeats — block {}…", + &addr.hex()[..16] + ); + if let Some(n) = direct { + eprintln!(" name: {n}"); + } + eprintln!(" {} named member(s):", members.len()); + for m in members.iter().take(40) { + eprintln!(" {m}"); + } + if members.len() > 40 { + eprintln!(" … and {} more", members.len() - 40); + } + } +} diff --git a/crates/kernel/examples/manifest_info.rs b/crates/kernel/examples/manifest_info.rs new file mode 100644 index 00000000..57f02854 --- /dev/null +++ b/crates/kernel/examples/manifest_info.rs @@ -0,0 +1,26 @@ +//! Inspect a `.ixes` manifest: list the heaviest shards (index, heartbeats, +//! block count) so you can target one with the host's `--only-shard`. +//! +//! cargo run -p ix-kernel --release --example manifest_info -- + +use ix_kernel::shard::ShardManifest; + +fn main() { + let path = std::env::args().nth(1).expect("usage: manifest_info "); + let bytes = std::fs::read(&path).expect("read .ixes"); + let m = ShardManifest::from_bytes(&bytes).expect("parse .ixes"); + let mut idx: Vec<(usize, u64, usize)> = m + .shards + .iter() + .enumerate() + .map(|(i, s)| (i, s.heartbeats, s.blocks.len())) + .collect(); + idx.sort_by(|a, b| b.1.cmp(&a.1)); + println!("{} shards. Heaviest:", m.num_shards); + for (i, hb, nb) in idx.iter().take(6) { + println!( + " manifest index {i}: {hb} heartbeats, {nb} block(s) → host --only-shard {}", + i + 1 + ); + } +} diff --git a/crates/kernel/examples/perf_check.rs b/crates/kernel/examples/perf_check.rs new file mode 100644 index 00000000..a8c9869b --- /dev/null +++ b/crates/kernel/examples/perf_check.rs @@ -0,0 +1,73 @@ +//! Native re-run of the SP1/Zisk guest's `check_const` loop, used to gather +//! data the zkVM guests cannot surface from inside the proof environment. +//! +//! `crates/kernel/src/lib.rs` short-circuits every `IX_*` env-var read on +//! `target_os = "zkvm"`, so the kernel's perf-counter infrastructure +//! (`crates/kernel/src/perf.rs`) is inert inside SP1/Zisk guests. Run this +//! native binary against the same `.ixe` to read cache hit rates, peak/avg +//! fuel per constant, and a wall-clock baseline. Combine with the SP1 +//! cycle-tracker output (see `sp1/host/src/main.rs` and +//! `sp1/guest/src/main.rs`) to attribute zkVM cycles to specific phases. +//! +//! IX_PERF_COUNTERS=1 cargo run --release --example perf_check -- path.ixe +//! +//! Mirrors `sp1/guest/src/main.rs` (Anon mode; no Meta-mode variant since +//! the cache and fuel behaviour is materially the same and Meta only adds +//! a few percent of cycles in the zkVM). + +use std::env; +use std::fs; +use std::time::Instant; + +use ix_kernel::id::KId; +use ix_kernel::ingress::ixon_ingress_owned; +use ix_kernel::mode::Anon; +use ix_kernel::tc::TypeChecker; +use ixon::env::Env as IxonEnv; +use ixon::metadata::ConstantMetaInfo; + +fn main() { + env_logger::builder() + .filter_level(log::LevelFilter::Info) + .format_timestamp(None) + .init(); + let path = env::args().nth(1).expect("usage: perf_check "); + let bytes = fs::read(&path).expect("read ixe"); + + // Collect (KId, pretty-name) pairs so the per-kid log lines line up with + // the `kid_NNN` labels printed by the SP1 guest's cycle tracker. + let env = IxonEnv::get(&mut &bytes[..]).expect("decode env"); + let entries: Vec<(KId, String)> = env + .named + .iter() + .filter(|e| !matches!(e.value().meta.info, ConstantMetaInfo::Muts { .. })) + .map(|e| (KId::::new(e.value().addr.clone(), ()), e.key().pretty())) + .collect(); + let kids: Vec> = entries.iter().map(|(k, _)| k.clone()).collect(); + eprintln!("[perf_check] env loaded: {} consts", kids.len()); + for (i, (_, name)) in entries.iter().enumerate() { + eprintln!(" kid_{i:03} {name}"); + } + + let t_ingress = Instant::now(); + let (mut kenv, _intern) = ixon_ingress_owned::(env).expect("ingress"); + eprintln!("[perf_check] ingress: {:>8.2?}", t_ingress.elapsed()); + + let t_check = Instant::now(); + let mut failures = 0u32; + let mut tc = TypeChecker::new(&mut kenv); + for kid in &kids { + if tc.check_const(kid).is_err() { + failures = failures.saturating_add(1); + } + } + eprintln!( + "[perf_check] check_const: {:>8.2?} ({} failures)", + t_check.elapsed(), + failures + ); + // Drop the TC first so its borrow on KEnv ends; KEnv's `Drop` is what + // actually dumps the `PerfCounters` summary when IX_PERF_COUNTERS=1. + drop(tc); + drop(kenv); +} diff --git a/crates/kernel/examples/shard_names.rs b/crates/kernel/examples/shard_names.rs new file mode 100644 index 00000000..6c5d0745 --- /dev/null +++ b/crates/kernel/examples/shard_names.rs @@ -0,0 +1,62 @@ +//! Name the member defs of given shards of a `.ixes` manifest. +//! +//! cargo run -p ix-kernel --release --example shard_names -- ... + +use std::collections::HashMap; + +use ix_common::address::Address; +use ix_kernel::shard::ShardManifest; +use ixon::constant::ConstantInfo as CI; +use ixon::env::Env as IxonEnv; + +fn block_of(env: &IxonEnv, addr: &Address) -> Address { + match env.get_const(addr) { + Some(c) => match &c.info { + CI::IPrj(p) => p.block.clone(), + CI::CPrj(p) => p.block.clone(), + CI::RPrj(p) => p.block.clone(), + CI::DPrj(p) => p.block.clone(), + _ => addr.clone(), + }, + None => addr.clone(), + } +} + +fn main() { + let a: Vec = std::env::args().collect(); + let ixe = &a[1]; + let ixes = &a[2]; + let idxs: Vec = a[3..].iter().filter_map(|s| s.parse().ok()).collect(); + + let env = IxonEnv::get(&mut &std::fs::read(ixe).unwrap()[..]).expect("get"); + let m = ShardManifest::from_bytes(&std::fs::read(ixes).unwrap()).expect("manifest"); + + // block address -> member def names (group named consts by their home block). + let mut block2names: HashMap> = HashMap::new(); + for e in env.named.iter() { + let blk = block_of(&env, &e.value().addr); + block2names.entry(blk).or_default().push(e.key().to_string()); + } + + for idx in idxs { + let s = &m.shards[idx]; + println!("\n=== shard {idx}: {} block(s), {} heartbeats ===", s.blocks.len(), s.heartbeats); + let mut shown = 0; + for b in &s.blocks { + let mut names = block2names.get(b).cloned().unwrap_or_default(); + names.sort(); + names.dedup(); + if shown < 12 { + if names.is_empty() { + println!(" {}… (no named member)", &b.hex()[..16]); + } else { + println!(" {}… {}", &b.hex()[..16], names.join(", ")); + } + } + shown += 1; + } + if s.blocks.len() > 12 { + println!(" … and {} more block(s)", s.blocks.len() - 12); + } + } +} diff --git a/crates/kernel/examples/shard_plan.rs b/crates/kernel/examples/shard_plan.rs new file mode 100644 index 00000000..826d5899 --- /dev/null +++ b/crates/kernel/examples/shard_plan.rs @@ -0,0 +1,337 @@ +//! Generate a `.ixes` sharding manifest from a `.ixe` env, out of circuit — a +//! standalone equivalent of `ix profile` + `ix shard` that does NOT go through +//! the Lean/FFI layer. Useful for producing a plan to feed the Zisk host's +//! `--shard-plan`, and for iterating the partitioner without a full Lean build. +//! +//! Usage: +//! cargo run -p ix-kernel --release --example shard_plan -- \ +//! [--shards N | --max-cycles C] [--ram-gb G] [--cycles-per-heartbeat K] [--out path] +//! +//! By DEFAULT (no flags) it sizes the shard count automatically from this +//! machine's total RAM (`/proc/meminfo`): RAM → per-shard cycle cap (prover +//! model `peak_RAM_GB ≈ 45 + 32 × cycles_billions`, ~78% of RAM) → cap ÷ +//! cycles-per-heartbeat → N from total heartbeats. So you just hand it the +//! `.ixe`; no budget to pick. +//! +//! --shards N force exactly N shards (skip the estimate). +//! --max-cycles C force a per-shard guest-cycle budget (skip RAM read). +//! --ram-gb G override detected RAM (for what-if sizing). +//! --cycles-per-heartbeat K heartbeat→cycle conversion (default 215000, +//! measured across envs; recalibrate per env with one +//! `--execute`: a shard's steps ÷ its heartbeats). +//! --out path output .ixes (default .ixes). +//! +//! Profiles the env with the real kernel (single worker, cache-isolated so +//! heartbeats reflect un-memoized in-circuit cost and every delta-unfold is +//! recorded), aggregates per-constant records into a block profile, partitions, +//! and writes the manifest. + +use ix_common::address::Address; +use ix_kernel::anon_work::build_anon_work; +use ix_kernel::env::KEnv; +use ix_kernel::id::KId; +use ix_kernel::mode::Anon; +use ix_kernel::profile::{BlockProfile, ProfileBuilder, ProfileSink}; +use ix_kernel::shard::{ + cycle_cap_for_ram, partition_for_cycle_cap, Hypergraph, ShardManifest, +}; +use ix_kernel::tc::TypeChecker; +use ixon::constant::ConstantInfo as CI; +use ixon::env::Env as IxonEnv; + +/// Map a constant to its ingress block: a projection's `block` address, +/// otherwise the constant itself (mirrors the FFI profiler's `profile_block_of`). +fn block_of(env: &IxonEnv, addr: &Address) -> Address { + match env.get_const(addr) { + Some(c) => match &c.info { + CI::IPrj(p) => p.block.clone(), + CI::CPrj(p) => p.block.clone(), + CI::RPrj(p) => p.block.clone(), + CI::DPrj(p) => p.block.clone(), + _ => addr.clone(), + }, + None => addr.clone(), + } +} + +fn block_size(env: &IxonEnv, block: &Address) -> u32 { + env.get_const_bytes(block).map_or(0, |b| b.len().min(u32::MAX as usize) as u32) +} + +/// Parse a count that may use float/scientific notation (e.g. `4.5e9`). +fn parse_count(s: &str) -> u64 { + let v: f64 = s.parse().unwrap_or_else(|_| { + eprintln!("error: not a number: {s}"); + std::process::exit(1); + }); + if v < 0.0 { + eprintln!("error: must be non-negative: {s}"); + std::process::exit(1); + } + v as u64 +} + +/// Total RAM in GiB from `/proc/meminfo` (`None` off-Linux / on parse failure). +fn detect_ram_gb() -> Option { + let s = std::fs::read_to_string("/proc/meminfo").ok()?; + let line = s.lines().find(|l| l.starts_with("MemTotal:"))?; + let kb: f64 = line.split_whitespace().nth(1)?.parse().ok()?; + Some(kb / 1024.0 / 1024.0) +} + +fn usage() -> ! { + eprintln!( + "usage: shard_plan [--shards N | --max-cycles C] \ + [--ram-gb G] [--cycles-per-heartbeat K] [--store-dir dir] [--out path]" + ); + eprintln!( + " default: size N automatically from this machine's RAM (/proc/meminfo).\n \ + --shards N forces a count; --max-cycles C forces a per-shard cycle budget;\n \ + --ram-gb G overrides detected RAM.\n \ + --store-dir dir: store-aware planning — work items whose targets are all\n \ + covered by the proof store are excluded (not profiled, not partitioned);\n \ + the manifest covers only NOVEL work. The prover resolves the covered\n \ + remainder by folding the store's proofs (zisk-host --store-dir)." + ); + std::process::exit(1); +} + +/// The proof store's covered-target set: the union of `proofs/*.cover` +/// (packed 32-byte addresses), exactly as `zisk-host --store-dir` writes them. +fn load_covered(dir: &str) -> std::collections::HashSet
{ + let pdir = std::path::Path::new(dir).join("proofs"); + let mut covered = std::collections::HashSet::new(); + for idx in 0.. { + let Ok(bytes) = std::fs::read(pdir.join(format!("{idx}.cover"))) else { + break; + }; + covered.extend(Address::unpack(&bytes)); + } + covered +} + +fn main() { + // ---- Parse args. ---- + let args: Vec = std::env::args().collect(); + let mut path: Option = None; + let mut shards: Option = None; + let mut naive = false; + let mut max_cycles: Option = None; + // Default heartbeat→cycle ratio. Measured across 12 envs: large, shardable + // envs (>20k hb) cluster at 194–208k whole-env; the per-shard ratio runs + // higher (less memoization) — mergesort's heaviest shard is ~216k. 215k is + // that per-shard value (the conservative end for the regime that needs + // sharding). Tiny envs run lower (~130–160k, cheap arithmetic); a couple of + // mid envs run ~258k (heavy def-eq) — recalibrate those via --execute. + let mut cyc_per_hb: u64 = 215_000; + let mut ram_gb: Option = None; + let mut store_dir: Option = None; + let mut out: Option = None; + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--naive" => { + naive = true; + }, + "--shards" => { + i += 1; + shards = Some(parse_count(args.get(i).unwrap_or(&String::new())) as usize); + }, + "--max-cycles" => { + i += 1; + max_cycles = Some(parse_count(args.get(i).unwrap_or(&String::new()))); + }, + "--cycles-per-heartbeat" => { + i += 1; + cyc_per_hb = parse_count(args.get(i).unwrap_or(&String::new())).max(1); + }, + "--ram-gb" => { + i += 1; + ram_gb = args.get(i).and_then(|s| s.parse::().ok()); + }, + "--store-dir" => { + i += 1; + store_dir = args.get(i).cloned(); + }, + "--out" => { + i += 1; + out = args.get(i).cloned(); + }, + s if s.starts_with("--") => { + eprintln!("error: unknown flag {s}"); + usage(); + }, + s if path.is_none() => path = Some(s.to_string()), + s => { + eprintln!("error: unexpected argument {s}"); + usage(); + }, + } + i += 1; + } + let Some(path) = path else { usage() }; + if shards.is_some() && max_cycles.is_some() { + eprintln!("error: pass at most one of --shards / --max-cycles"); + usage(); + } + let out = out.unwrap_or_else(|| format!("{path}.ixes")); + + // ---- Store-aware planning: drop work the store already covers. ---- + // A work item is covered iff every target it would certify is in the store + // (the same rule the prover applies per shard). Covered items are not + // profiled (no point typechecking them again) and not partitioned — they're + // resolved at prove time by folding the store's proofs. Covered BLOCKS are + // also excluded from the hypergraph: a novel→covered delta edge is an + // assumption discharged at aggregation, not a cut to minimize. + let covered: std::collections::HashSet
= + store_dir.as_deref().map(load_covered).unwrap_or_default(); + let covered_item = + |item: &ix_kernel::anon_work::AnonWorkItem| -> bool { + !covered.is_empty() + && item.proven_targets().iter().all(|t| covered.contains(t)) + }; + + // ---- Profile: run the kernel, recording heartbeats + delta-unfold edges. ---- + let bytes = std::fs::read(&path).expect("read .ixe"); + let env = IxonEnv::get_anon(&mut &bytes[..]).expect("invalid Ixon environment"); + let work = build_anon_work(&env).expect("build_anon_work"); + let (novel_work, covered_work): (Vec<_>, Vec<_>) = + work.iter().partition(|item| !covered_item(item)); + // Blocks whose work item is covered — excluded from the hypergraph below. + let covered_blocks: std::collections::HashSet
= covered_work + .iter() + .map(|item| block_of(&env, item.primary())) + .collect(); + if novel_work.is_empty() { + eprintln!( + "nothing to plan: the store covers all {} work items", + work.len() + ); + std::process::exit(0); + } + + let mut kenv = KEnv::::new(); + kenv.profile_sink = Some(ProfileSink::new(true)); // isolate = sound recording + let mut failures = 0usize; + for item in &novel_work { + let kid = KId::::new(item.primary().clone(), ()); + let mut tc = TypeChecker::::new_with_lazy_anon(&mut kenv, &env); + if tc.check_const(&kid).is_err() { + failures += 1; + } + tc.finish_constant_accounting(); + } + let sink = kenv.profile_sink.take().expect("profile sink"); + + // ---- Aggregate per-constant records into a block-level BlockProfile. ---- + let mut builder = ProfileBuilder::new(); + for (consumer, rec) in &sink.records { + let cb = block_of(&env, consumer); + let cs = block_size(&env, &cb); + builder.block(cb.clone(), rec.fuel, cs, 1); + for prod in &rec.producers { + let pb = block_of(&env, prod); + if covered_blocks.contains(&pb) { + continue; // assumption against the store, not a partition edge + } + let ps = block_size(&env, &pb); + builder.block(pb.clone(), 0, ps, 0); + builder.delta_edge(cb.clone(), pb); + } + } + let profile: BlockProfile = builder.finish(); + + // ---- Choose the partition. Default: size N from the machine's RAM (no + // budget needed). --shards N forces a count; --max-cycles C forces a budget. + let (shard_of, n, tree) = if let (true, Some(n)) = (naive, shards) { + // Naive baseline: group blocks into N contiguous (address-sorted) chunks, + // ignoring the delta graph — to isolate the value of smart grouping. No + // bisection tree (the prover falls back to a flat fold). + let nb = profile.num_blocks(); + let chunk = nb.div_ceil(n.max(1)).max(1); + let shard_of: Vec = + (0..nb).map(|b| ((b / chunk).min(n - 1)) as u32).collect(); + eprintln!("naive grouping into {n} contiguous block chunks"); + (shard_of, n, None) + } else if let Some(n) = shards { + let h = Hypergraph::from_profile(&profile); + let (so, t) = h.partition_with_tree(n, 0.05); + (so, n, Some(t)) + } else { + // Per-shard cycle cap: explicit --max-cycles, else derived from RAM. + let cap = match max_cycles { + Some(c) => { + eprintln!("budget: --max-cycles {c}"); + c + }, + None => { + let ram = ram_gb.or_else(detect_ram_gb).unwrap_or_else(|| { + eprintln!("warning: could not read /proc/meminfo; assuming 256 GB (override with --ram-gb)"); + 256.0 + }); + let c = cycle_cap_for_ram(ram); + if c == 0 { + eprintln!( + "error: {ram:.0} GB RAM is below the ~45 GB prover base — nothing will \ + prove on this machine." + ); + std::process::exit(1); + } + eprintln!( + "auto: machine RAM {ram:.0} GB → per-shard cap ~{c} cycles \ + (~78% RAM via prover model peak_GB≈45+32·Bcyc)" + ); + c + }, + }; + let plan = partition_for_cycle_cap(&profile, cap, cyc_per_hb, 0.05); + let cyc = u128::from(plan.max_shard_heartbeats) * u128::from(cyc_per_hb); + let floor_cyc = + u128::from(plan.largest_block_heartbeats) * u128::from(cyc_per_hb); + eprintln!( + " total heartbeats {} → heartbeat_cap {} (@ {cyc_per_hb} cyc/hb) → N={}", + profile.total_heartbeats(), + plan.heartbeat_cap, + plan.num_shards, + ); + eprintln!( + " heaviest shard: {} hb (~{cyc} cycles); largest atomic block: {} hb (~{floor_cyc} cycles)", + plan.max_shard_heartbeats, plan.largest_block_heartbeats, + ); + if plan.infeasible_atomic_floor { + eprintln!( + " WARNING: the largest atomic (mutual) block alone exceeds the cap — NO \ + shard count can fit it. Split that block upstream (Lean side) or use a \ + bigger box." + ); + } else if plan.max_shard_heartbeats > plan.heartbeat_cap { + eprintln!( + " note: heaviest shard still over cap at N={} (pinned by the atomic-block \ + floor); more shards won't lower it.", + plan.num_shards, + ); + } + (plan.shard_of, plan.num_shards, Some(plan.tree)) + }; + + // ---- Manifest. ---- + let mut manifest = ShardManifest::build(&profile, &shard_of, n); + if let Some(t) = tree { + manifest = manifest.with_tree(t); + } + for s in &mut manifest.shards { + s.assumption_root = ixon::merkle::merkle_root_canonical(&s.foreign_blocks); + } + std::fs::write(&out, manifest.to_bytes()).expect("write .ixes manifest"); + + eprintln!( + "profiled {} novel work items ({} store-covered skipped, {failures} failure(s)), \ + {} blocks, {} delta edges → {} shards; wrote {out}", + novel_work.len(), + covered_work.len(), + profile.num_blocks(), + profile.num_edges(), + manifest.num_shards, + ); + eprintln!("{}", manifest.summary()); +} diff --git a/src/ix/kernel/anon_env.rs b/crates/kernel/src/anon_env.rs similarity index 95% rename from src/ix/kernel/anon_env.rs rename to crates/kernel/src/anon_env.rs index cfc18168..fe8375f7 100644 --- a/src/ix/kernel/anon_env.rs +++ b/crates/kernel/src/anon_env.rs @@ -24,9 +24,9 @@ use rustc_hash::FxHashSet; use std::collections::VecDeque; use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::ixon::constant::Constant; -use crate::ix::ixon::env::Env as IxonEnv; +use ix_common::address::Address; +use ixon::constant::Constant; +use ixon::env::Env as IxonEnv; /// Anonymous-only view over an `IxonEnv`. #[derive(Clone, Copy, Debug)] @@ -103,10 +103,10 @@ impl<'a> AnonEnv<'a> { #[cfg(test)] mod tests { use super::*; - use crate::ix::env::Name; - use crate::ix::ixon::constant::{Axiom, ConstantInfo}; - use crate::ix::ixon::env::Named; - use crate::ix::ixon::expr::Expr; + use ix_common::env::Name; + use ixon::constant::{Axiom, ConstantInfo}; + use ixon::env::Named; + use ixon::expr::Expr; fn axiom_const_with_refs(refs: Vec
) -> Constant { Constant::with_tables( diff --git a/crates/kernel/src/anon_work.rs b/crates/kernel/src/anon_work.rs new file mode 100644 index 00000000..519b1ab6 --- /dev/null +++ b/crates/kernel/src/anon_work.rs @@ -0,0 +1,179 @@ +//! Anon-mode work enumeration over `IxonEnv::consts`. +//! +//! Identifies the set of kernel-checkable target addresses without +//! consulting any metadata sections (`named`/`names`/`comms`), so it +//! works against an env loaded via [`ixon::env::Env::get_anon`]. +//! +//! The set produced here is the canonical work set for anon-mode +//! typechecking: it matches `rs_kernel_check_anon` in +//! `crates/ffi/src/kernel.rs` and is what an Aiur-style verifier +//! commits to. Callers iterate the returned `Vec` and +//! invoke `TypeChecker::check_const` on each item's `primary` address; +//! the kernel's internal block coordination handles checking every +//! member + ctor of `Block` items. +//! +//! ## Enumeration rules +//! +//! For each entry in `env.consts`: +//! - Projection variants (IPrj/CPrj/RPrj/DPrj) are skipped — they're +//! covered by checking their parent Muts block. +//! - Standalone variants (Defn/Recr/Axio/Quot) emit one `Standalone` +//! work item with the constant's own address. +//! - Muts blocks materialize to enumerate members, then emit one +//! `Block` item whose `primary` is the first member's projection +//! address (and `targets` includes that primary plus every other +//! member's projection plus one CPrj per constructor of each +//! inductive member). Checking the primary triggers the kernel's +//! block-coordination logic which covers every target. +//! +//! Dispatch on the outer `Tag4` byte via +//! [`ixon::lazy::LazyConstant::peek_variant`] avoids body parse + +//! `Arc` allocation for the ~95% of constants that are +//! standalones or projections. + +use ix_common::address::Address; +use ixon::env::Env as IxonEnv; +use ixon::lazy::ConstVariantTag; + +use crate::ingress::{ + anon_ctor_proj_addr, anon_defn_proj_addr, anon_indc_proj_addr, + anon_recr_proj_addr, +}; + +/// A single anon-mode work item — one `tc.check_const(primary)` per +/// item suffices to typecheck every address in `targets`. +#[derive(Clone, Debug)] +pub enum AnonWorkItem { + /// A standalone (Defn/Recr/Axio/Quot) constant. `addr` is both the + /// kernel-checked target and the only address this item covers. + Standalone { addr: Address }, + /// A Muts block. Checking `primary` (the first member's projection + /// address) drives the kernel's block coordination, which in turn + /// typechecks every entry in `targets`. `targets[0] == primary`. + /// `block_addr` is the block's own `env.consts` key (the `Tag::Muts` + /// entry) — distinct from the projection `targets`, and the address + /// other constants' `refs` use to reference the block. Carried so the + /// set of `consts` keys a checked item certifies ([`proven_targets`]) + /// is in the same address space as `Constant.refs`. + /// + /// [`proven_targets`]: AnonWorkItem::proven_targets + Block { block_addr: Address, primary: Address, targets: Vec
}, +} + +impl AnonWorkItem { + /// The address to pass to `tc.check_const`. + pub fn primary(&self) -> &Address { + match self { + AnonWorkItem::Standalone { addr } => addr, + AnonWorkItem::Block { primary, .. } => primary, + } + } + + /// Every kernel-checked target this item covers (one for + /// `Standalone`, `targets.len()` for `Block`). + pub fn targets(&self) -> &[Address] { + match self { + AnonWorkItem::Standalone { addr } => core::slice::from_ref(addr), + AnonWorkItem::Block { targets, .. } => targets, + } + } + + /// Every `env.consts` key this item certifies (proves) well-typed when + /// its `primary` is checked — the *proven targets*, in the same address + /// space as `Constant.refs`, so a dependency ref can be matched against + /// the union of `proven_targets()` over all checked items: refs in that + /// union are already certified, the rest are the claim's open assumptions + /// (resolved later against other proofs). Unlike + /// [`targets`](Self::targets) (the addresses the kernel actually walks), + /// a `Block`'s proven set also includes the block's own `consts` key: + /// for a `Standalone` it's just its address; for a `Block` it's + /// `block_addr` plus every projection target (members + ctors). The + /// union of `proven_targets()` over a full `build_anon_work` is exactly + /// `env.consts.keys()`. + pub fn proven_targets(&self) -> Vec
{ + match self { + AnonWorkItem::Standalone { addr } => vec![addr.clone()], + AnonWorkItem::Block { block_addr, targets, .. } => { + let mut v = Vec::with_capacity(1 + targets.len()); + v.push(block_addr.clone()); + v.extend(targets.iter().cloned()); + v + }, + } + } +} + +/// Enumerate the anon-mode kernel work set from `env.consts`. +/// +/// Returns one `AnonWorkItem` per kernel-checkable group of +/// constants. The total number of checked target addresses is +/// `work.iter().map(|w| w.targets().len()).sum()`. +/// +/// Errors only on a corrupted env (missing const at an enumerated +/// address, or a Tag4 head byte that doesn't correspond to a known +/// `ConstantInfo` variant). +pub fn build_anon_work(env: &IxonEnv) -> Result, String> { + use ixon::constant::ConstantInfo as CI; + use ixon::constant::MutConst as MC; + use ConstVariantTag as Tag; + + let mut work: Vec = Vec::new(); + + // Sort keys for deterministic ordering across runs. + let mut keys: Vec
= + env.consts.iter().map(|e| e.key().clone()).collect(); + keys.sort_unstable(); + + for addr in keys { + let lc = env.consts.get(&addr).ok_or_else(|| { + format!("build_anon_work: missing const at {}", addr.hex()) + })?; + let tag = lc.value().peek_variant().map_err(|e| { + format!("build_anon_work: peek_variant {}: {e}", addr.hex()) + })?; + match tag { + Tag::IPrj | Tag::CPrj | Tag::RPrj | Tag::DPrj => { + // Skip — covered by parent block. + }, + Tag::Defn | Tag::Recr | Tag::Axio | Tag::Quot => { + work.push(AnonWorkItem::Standalone { addr: addr.clone() }); + }, + Tag::Muts => { + // Materialize once to enumerate members; the `Arc` + // drops at the end of this arm — no cache retention. + let constant = lc.value().get().map_err(|e| { + format!("build_anon_work: materialize Muts {}: {e}", addr.hex()) + })?; + let CI::Muts(members) = &constant.info else { + return Err(format!( + "build_anon_work: Tag::Muts but ConstantInfo is {:?} at {}", + constant.info.variant(), + addr.hex() + )); + }; + let mut targets: Vec
= Vec::new(); + for (i, member) in members.iter().enumerate() { + let i = i as u64; + let member_addr = match member { + MC::Defn(_) => anon_defn_proj_addr(&addr, i), + MC::Indc(_) => anon_indc_proj_addr(&addr, i), + MC::Recr(_) => anon_recr_proj_addr(&addr, i), + }; + targets.push(member_addr); + if let MC::Indc(ind) = member { + for cidx in 0..ind.ctors.len() as u64 { + targets.push(anon_ctor_proj_addr(&addr, i, cidx)); + } + } + } + if targets.is_empty() { + continue; + } + let primary = targets[0].clone(); + work.push(AnonWorkItem::Block { block_addr: addr.clone(), primary, targets }); + }, + } + } + + Ok(work) +} diff --git a/src/ix/kernel/canonical_check.rs b/crates/kernel/src/canonical_check.rs similarity index 99% rename from src/ix/kernel/canonical_check.rs rename to crates/kernel/src/canonical_check.rs index 68429f99..9c028fec 100644 --- a/src/ix/kernel/canonical_check.rs +++ b/crates/kernel/src/canonical_check.rs @@ -38,7 +38,7 @@ use std::cmp::Ordering; use rustc_hash::FxHashMap; -use crate::ix::address::Address; +use ix_common::address::Address; use super::constant::{KConst, RecRule}; use super::error::TcError; @@ -47,7 +47,7 @@ use super::id::KId; use super::level::{KUniv, UnivData}; use super::mode::KernelMode; -pub use crate::ix::strong_ordering::SOrd; +pub use ix_common::strong_ordering::SOrd; // =========================================================================== // KMutCtx — block-local address → class-index map @@ -415,11 +415,11 @@ fn compare_krecr( /// alpha-collapse on the canonical IXON form, which doesn't include /// hints (and treats safety as a separate sidecar in practice). fn compare_kdefn( - x_kind: crate::ix::ixon::constant::DefKind, + x_kind: ixon::constant::DefKind, x_lvls: u64, x_ty: &KExpr, x_val: &KExpr, - y_kind: crate::ix::ixon::constant::DefKind, + y_kind: ixon::constant::DefKind, y_lvls: u64, y_ty: &KExpr, y_val: &KExpr, @@ -826,10 +826,10 @@ pub fn validate_canonical_block_single_pass( #[cfg(test)] mod tests { use super::*; - use crate::ix::address::Address; - use crate::ix::env::{BinderInfo, Name}; - use crate::ix::env::{DefinitionSafety, ReducibilityHints}; - use crate::ix::ixon::constant::DefKind; + use ix_common::address::Address; + use ix_common::env::{BinderInfo, Name}; + use ix_common::env::{DefinitionSafety, ReducibilityHints}; + use ixon::constant::DefKind; use super::super::expr::KExpr; use super::super::level::KUniv; diff --git a/src/ix/kernel/check.rs b/crates/kernel/src/check.rs similarity index 96% rename from src/ix/kernel/check.rs rename to crates/kernel/src/check.rs index 0b0f9764..79ae29ac 100644 --- a/src/ix/kernel/check.rs +++ b/crates/kernel/src/check.rs @@ -1,13 +1,12 @@ //! Constant checking dispatch. -use std::sync::LazyLock; use std::time::{Duration, Instant}; use rustc_hash::FxHashSet; -use crate::ix::address::Address; -use crate::ix::env::{DefinitionSafety, QuotKind}; -use crate::ix::ixon::constant::DefKind; +use ix_common::address::Address; +use ix_common::env::{DefinitionSafety, QuotKind}; +use ixon::constant::DefKind; use super::constant::KConst; use super::env::Addr; @@ -26,14 +25,20 @@ use super::tc::TypeChecker; /// `IX_DECL_DIFF=1` we dump `val_ty` / `ty` and their whnf forms to /// pinpoint which sub-expression is stuck \u2014 sister tool to /// `IX_APP_DIFF` in `infer.rs`. -static IX_DECL_DIFF: LazyLock = - LazyLock::new(|| std::env::var("IX_DECL_DIFF").is_ok()); +#[cfg(not(target_arch = "riscv64"))] +static IX_DECL_DIFF: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_DECL_DIFF").is_ok()); +#[cfg(target_arch = "riscv64")] +static IX_DECL_DIFF: crate::EnvFlag = crate::EnvFlag::new(|| false); /// Per-phase timing for `Defn` checks. Set `IX_PHASE_TIMING=1` to see where a /// slow constant spends its time. Noisy — gate on a single constant via focus /// mode so only one line is printed. -static IX_PHASE_TIMING: LazyLock = - LazyLock::new(|| std::env::var("IX_PHASE_TIMING").is_ok()); +#[cfg(not(target_arch = "riscv64"))] +static IX_PHASE_TIMING: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_PHASE_TIMING").is_ok()); +#[cfg(target_arch = "riscv64")] +static IX_PHASE_TIMING: crate::EnvFlag = crate::EnvFlag::new(|| false); #[derive(Clone, Copy, Debug, Default)] struct ValidationTiming { @@ -67,7 +72,7 @@ impl TypeChecker<'_, M> { /// Type-check a single constant. Clears per-constant caches first. pub fn check_const(&mut self, id: &KId) -> Result<(), TcError> where - M::MField>: CheckDupLevelParams, + M::MField>: CheckDupLevelParams, { let c = self.get_const(id)?; if let Some(block) = self.coordinated_block_for(&c)? { @@ -84,7 +89,7 @@ impl TypeChecker<'_, M> { fn check_const_member_fresh(&mut self, id: &KId) -> Result<(), TcError> where - M::MField>: CheckDupLevelParams, + M::MField>: CheckDupLevelParams, { self.reset(); self.begin_const(id); @@ -99,7 +104,7 @@ impl TypeChecker<'_, M> { c: &KConst, ) -> Result<(), TcError> where - M::MField>: CheckDupLevelParams, + M::MField>: CheckDupLevelParams, { let phase_timing = *IX_PHASE_TIMING; let overall = if phase_timing { Some(Instant::now()) } else { None }; @@ -154,16 +159,16 @@ impl TypeChecker<'_, M> { // (delta, iota, native, ...) is missing for convergence. let val_ty_whnf = self.whnf(&val_ty); let ty_whnf = self.whnf(ty); - eprintln!("[decl diff] DeclTypeMismatch"); - eprintln!(" val_ty: {val_ty}"); - eprintln!(" ty: {ty}"); + log::info!("[decl diff] DeclTypeMismatch"); + log::info!(" val_ty: {val_ty}"); + log::info!(" ty: {ty}"); match &val_ty_whnf { - Ok(w) => eprintln!(" val_ty whnf: {w}"), - Err(e) => eprintln!(" val_ty whnf: ERR {e}"), + Ok(w) => log::info!(" val_ty whnf: {w}"), + Err(e) => log::info!(" val_ty whnf: ERR {e}"), } match &ty_whnf { - Ok(w) => eprintln!(" ty whnf: {w}"), - Err(e) => eprintln!(" ty whnf: ERR {e}"), + Ok(w) => log::info!(" ty whnf: {w}"), + Err(e) => log::info!(" ty whnf: ERR {e}"), } } return Err(TcError::DeclTypeMismatch); @@ -187,7 +192,7 @@ impl TypeChecker<'_, M> { if let Some(t0) = overall && self.phase_timing_label_matches(id) { - eprintln!( + log::info!( "[phase] {} total={:>8.1?} dup_lvls={:>8.1?} validate={:>8.1?} validate_ty={:>8.1?} validate_val={:>8.1?} validate_rules={:>8.1?} validate_univ={:>8.1?} infer_ty={:>8.1?} infer_val={:>8.1?} def_eq={:>8.1?} safety={:>8.1?} safety_ty={:>8.1?} safety_val={:>8.1?}", id, t0.elapsed(), @@ -335,7 +340,7 @@ impl TypeChecker<'_, M> { requested: &KId, ) -> Result<(), TcError> where - M::MField>: CheckDupLevelParams, + M::MField>: CheckDupLevelParams, { let phase_timing = *IX_PHASE_TIMING; let overall = if phase_timing { Some(Instant::now()) } else { None }; @@ -390,7 +395,7 @@ impl TypeChecker<'_, M> { if let Some(t0) = overall && self.phase_timing_label_matches(block) { - eprintln!( + log::info!( "[phase-block] {} kind={:?} members={} total={:>8.1?} get_members={:>8.1?} prevalidate={:>8.1?} validate_ty={:>8.1?} validate_val={:>8.1?} validate_rules={:>8.1?} validate_univ={:>8.1?} classify={:>8.1?} body={:>8.1?}", block, kind, @@ -479,7 +484,7 @@ impl TypeChecker<'_, M> { } fn phase_timing_label_matches(&self, id: &KId) -> bool { - match std::env::var("IX_KERNEL_DEBUG_CONST") { + match crate::env_var("IX_KERNEL_DEBUG_CONST") { Ok(filter) if filter.is_empty() => true, Ok(filter) => { id.to_string().contains(&filter) @@ -867,15 +872,15 @@ mod tests { use super::super::level::KUniv; use super::super::mode::Anon; use super::super::tc::TypeChecker; - use crate::ix::address::Address; - use crate::ix::env::{DefinitionSafety, ReducibilityHints}; - use crate::ix::ixon::constant::DefKind; + use ix_common::address::Address; + use ix_common::env::{DefinitionSafety, ReducibilityHints}; + use ixon::constant::DefKind; #[test] fn profile_sink_records_delta_edge_and_fuel() { - use crate::ix::kernel::mode::Meta; - use crate::ix::kernel::testing as t; - use crate::ix::profile::ProfileSink; + use crate::mode::Meta; + use crate::testing as t; + use crate::profile::ProfileSink; // g : Sort 2 := Sort 1 — a Definition, delta-reducible to Sort 1. let (g_id, g) = t::mk_defn( @@ -1139,13 +1144,13 @@ mod tests { #[test] fn check_duplicate_level_params_rejected() { - use crate::ix::kernel::mode::Meta; + use crate::mode::Meta; type ME = KExpr; type MU = KUniv; let mut env = KEnv::::new(); let dup_name = - crate::ix::env::Name::str(crate::ix::env::Name::anon(), "u".into()); + ix_common::env::Name::str(ix_common::env::Name::anon(), "u".into()); let id = KId::new(mk_addr("T"), dup_name.clone()); env.insert( id.clone(), diff --git a/src/ix/kernel/claim.rs b/crates/kernel/src/claim.rs similarity index 96% rename from src/ix/kernel/claim.rs rename to crates/kernel/src/claim.rs index 301300c7..32d63149 100644 --- a/src/ix/kernel/claim.rs +++ b/crates/kernel/src/claim.rs @@ -12,11 +12,11 @@ use rustc_hash::FxHashSet; -use crate::ix::address::Address; -use crate::ix::ixon::constant::ConstantInfo; -use crate::ix::ixon::env::Env; -use crate::ix::ixon::merkle::merkle_root_canonical; -use crate::ix::ixon::proof::Claim; +use ix_common::address::Address; +use ixon::constant::ConstantInfo; +use ixon::env::Env; +use ixon::merkle::merkle_root_canonical; +use ixon::proof::Claim; /// Canonical merkle root over the env's `consts.keys()`. Also called /// from the env serializer. Returns `None` for an empty const set. @@ -91,12 +91,12 @@ pub fn build_check_env_claim(env: &Env) -> Option { #[cfg(test)] mod tests { use super::*; - use crate::ix::env::DefinitionSafety; - use crate::ix::ixon::constant::{ + use ix_common::env::DefinitionSafety; + use ixon::constant::{ Axiom, Constant, ConstantInfo, DefKind, Definition, }; - use crate::ix::ixon::expr::Expr; - use crate::ix::ixon::merkle::leaf_hash; + use ixon::expr::Expr; + use ixon::merkle::leaf_hash; use std::sync::Arc; fn axiom_const(refs: Vec
) -> Constant { diff --git a/src/ix/kernel/congruence.rs b/crates/kernel/src/congruence.rs similarity index 97% rename from src/ix/kernel/congruence.rs rename to crates/kernel/src/congruence.rs index 2ba3ff44..906ae1b2 100644 --- a/src/ix/kernel/congruence.rs +++ b/crates/kernel/src/congruence.rs @@ -3,8 +3,8 @@ //! Validates that Ixon ingress in Anon mode produces structurally correct //! constants by comparing the Lean `ConstantInfo` against the loaded `KConst`. -use crate::ix::address::Address; -use crate::ix::env::{self as lean, ConstantInfo as LeanCI, Literal, Name}; +use ix_common::address::Address; +use ix_common::env::{self as lean, ConstantInfo as LeanCI, Literal, Name}; use super::constant::KConst; use super::expr::{ExprData, KExpr}; @@ -17,7 +17,7 @@ pub struct NameResolver { } impl NameResolver { - pub fn from_ixon_env(ixon_env: &crate::ix::ixon::env::Env) -> Self { + pub fn from_ixon_env(ixon_env: &ixon::env::Env) -> Self { let mut map = rustc_hash::FxHashMap::default(); for entry in ixon_env.named.iter() { map.insert(entry.key().clone(), entry.value().addr.clone()); @@ -364,22 +364,22 @@ fn zero_const_tag(c: &KConst) -> &'static str { #[cfg(test)] mod tests { use super::*; - use crate::ix::address::Address; - use crate::ix::env::{ + use crate::constant::KConst; + use crate::id::KId; + use crate::mode::Anon; + use ix_common::address::Address; + use ix_common::env::{ self, AxiomVal, BinderInfo, ConstantVal, ConstructorVal, DefinitionSafety, DefinitionVal, InductiveVal, Level as LL, Name, OpaqueVal, QuotKind, QuotVal, RecursorRule as LeanRule, RecursorVal, ReducibilityHints, TheoremVal, }; - use crate::ix::ixon::env::{Env as IxonEnv, Named}; - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::mode::Anon; + use ixon::env::{Env as IxonEnv, Named}; /// `Nat` from a u64 via the public `From` impl. /// (The `Nat` type itself is a private re-export in `env.rs`.) - fn n(x: u64) -> lean_ffi::nat::Nat { - lean_ffi::nat::Nat::from(x) + fn n(x: u64) -> bignat::Nat { + bignat::Nat::from(x) } // ---- test helpers ---- @@ -725,7 +725,7 @@ mod tests { let kc = KConst::::Defn { name: (), level_params: (), - kind: crate::ix::ixon::constant::DefKind::Definition, + kind: ixon::constant::DefKind::Definition, safety: DefinitionSafety::Safe, hints: ReducibilityHints::Opaque, lvls: 0, @@ -768,7 +768,7 @@ mod tests { let kc = KConst::::Defn { name: (), level_params: (), - kind: crate::ix::ixon::constant::DefKind::Definition, + kind: ixon::constant::DefKind::Definition, safety: DefinitionSafety::Safe, hints: ReducibilityHints::Opaque, lvls: 0, @@ -969,7 +969,7 @@ mod tests { let k = KConst::::Defn { name: (), level_params: (), - kind: crate::ix::ixon::constant::DefKind::Theorem, + kind: ixon::constant::DefKind::Theorem, safety: DefinitionSafety::Safe, hints: ReducibilityHints::Opaque, lvls: 0, diff --git a/src/ix/kernel/constant.rs b/crates/kernel/src/constant.rs similarity index 95% rename from src/ix/kernel/constant.rs rename to crates/kernel/src/constant.rs index 09bde5f0..16a3592b 100644 --- a/src/ix/kernel/constant.rs +++ b/crates/kernel/src/constant.rs @@ -3,8 +3,8 @@ //! Each variant carries structural fields plus metadata fields //! (`name`, `level_params`, `lean_all`) for roundtrip fidelity in Meta mode. -use crate::ix::env::{DefinitionSafety, Name, QuotKind, ReducibilityHints}; -use crate::ix::ixon::constant::DefKind; +use ix_common::env::{DefinitionSafety, Name, QuotKind, ReducibilityHints}; +use ixon::constant::DefKind; use super::expr::KExpr; use super::id::KId; @@ -153,9 +153,9 @@ mod tests { use super::super::level::KUniv; use super::super::mode::Anon; use super::*; - use crate::ix::address::Address; - use crate::ix::env::{DefinitionSafety, QuotKind, ReducibilityHints}; - use crate::ix::ixon::constant::DefKind; + use ix_common::address::Address; + use ix_common::env::{DefinitionSafety, QuotKind, ReducibilityHints}; + use ixon::constant::DefKind; fn sort0() -> KExpr { KExpr::sort(KUniv::zero()) diff --git a/src/ix/kernel/def_eq.rs b/crates/kernel/src/def_eq.rs similarity index 96% rename from src/ix/kernel/def_eq.rs rename to crates/kernel/src/def_eq.rs index a9323339..c0868636 100644 --- a/src/ix/kernel/def_eq.rs +++ b/crates/kernel/src/def_eq.rs @@ -7,9 +7,7 @@ //! 4. Iterative lazy delta with same-head-spine optimization //! 5. Full WHNF, structural comparison, eta, struct eta -use std::sync::LazyLock; - -use crate::ix::ixon::constant::DefKind; +use ixon::constant::DefKind; use super::constant::KConst; use super::env::Addr; @@ -29,28 +27,28 @@ use super::tc::{ /// to watch all `Int.bmod`-involving comparisons). Prints `[deq] a b` /// before entering `is_def_eq_inner`, then the boolean outcome. Useful for /// pinning down which sub-expression of an App-spine is stuck. -static IX_DEF_EQ_TRACE: LazyLock> = - LazyLock::new(|| std::env::var("IX_DEF_EQ_TRACE").ok()); +static IX_DEF_EQ_TRACE: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_DEF_EQ_TRACE").ok()); /// Global perf counter: total `is_def_eq` entries across all checks. /// When `IX_DEF_EQ_COUNT_LOG=1`, logs every 1M calls. Useful for /// detecting checks that explode into millions of recursive /// comparisons \u2014 a signal that some caching optimization is /// mis-firing or some reduction is looping. -static IX_DEF_EQ_COUNT_LOG: LazyLock = - LazyLock::new(|| std::env::var("IX_DEF_EQ_COUNT_LOG").is_ok()); +static IX_DEF_EQ_COUNT_LOG: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_DEF_EQ_COUNT_LOG").is_ok()); /// Dump the expression pair when `is_def_eq` hits its recursion/fuel guard. /// The optional env var value is used as a substring filter over the two head /// constants; an empty value dumps every guard hit. -static IX_DEF_EQ_MAX_DUMP: LazyLock> = - LazyLock::new(|| std::env::var("IX_DEF_EQ_MAX_DUMP").ok()); +static IX_DEF_EQ_MAX_DUMP: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_DEF_EQ_MAX_DUMP").ok()); -static IX_ETA_TRACE: LazyLock> = - LazyLock::new(|| std::env::var("IX_ETA_TRACE").ok()); +static IX_ETA_TRACE: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_ETA_TRACE").ok()); -static IX_PROJ_DELTA_TRACE: LazyLock> = - LazyLock::new(|| std::env::var("IX_PROJ_DELTA_TRACE").ok()); +static IX_PROJ_DELTA_TRACE: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_PROJ_DELTA_TRACE").ok()); static DEF_EQ_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); @@ -65,7 +63,7 @@ impl TypeChecker<'_, M> { if *IX_DEF_EQ_COUNT_LOG { let n = DEF_EQ_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); if n.is_multiple_of(100_000) && n > 0 { - eprintln!("[is_def_eq] count={n}"); + log::info!("[is_def_eq] count={n}"); } } if a.ptr_eq(b) { @@ -87,12 +85,12 @@ impl TypeChecker<'_, M> { let a_hit = head_const_name(a).is_some_and(|n| n.contains(prefix)); let b_hit = head_const_name(b).is_some_and(|n| n.contains(prefix)); if a_hit || b_hit { - eprintln!( + log::info!( "[deq] depth={} a={}", self.def_eq_depth, compact_def_eq_expr(a) ); - eprintln!( + log::info!( "[deq] depth={} b={}", self.def_eq_depth, compact_def_eq_expr(b) @@ -120,8 +118,8 @@ impl TypeChecker<'_, M> { // per method call. Any true result moves the originals into `add_equiv` // before returning. let eq_ctx = self.def_eq_ctx_key(a, b); - let a_key: crate::ix::kernel::equiv::EqKey = (a.hash_key(), eq_ctx); - let b_key: crate::ix::kernel::equiv::EqKey = (b.hash_key(), eq_ctx); + let a_key: crate::equiv::EqKey = (a.hash_key(), eq_ctx); + let b_key: crate::equiv::EqKey = (b.hash_key(), eq_ctx); if self.equiv_manager.is_equiv(&a_key, &b_key) { return Ok(true); @@ -211,7 +209,7 @@ impl TypeChecker<'_, M> { let ok = result?; if trace_active { - eprintln!( + log::info!( "[deq] depth={} -> {} ({})", self.def_eq_depth, ok, @@ -220,8 +218,8 @@ impl TypeChecker<'_, M> { // On FAIL, also dump the full a/b that failed (post-Tier-1 quick). // Lets us see what the def-eq engine actually compared. if !ok { - eprintln!("[deq fail] depth={} a-full: {a}", self.def_eq_depth); - eprintln!("[deq fail] depth={} b-full: {b}", self.def_eq_depth); + log::info!("[deq fail] depth={} a-full: {a}", self.def_eq_depth); + log::info!("[deq fail] depth={} b-full: {b}", self.def_eq_depth); } self.def_eq_trace_depth = self.def_eq_trace_depth.saturating_sub(1); } @@ -496,9 +494,9 @@ impl TypeChecker<'_, M> { } if self.def_eq_trace_depth > 0 { - eprintln!("[deq tier4 break] depth={}", self.def_eq_depth); - eprintln!(" wa: {wa}"); - eprintln!(" wb: {wb}"); + log::info!("[deq tier4 break] depth={}", self.def_eq_depth); + log::info!(" wa: {wa}"); + log::info!(" wb: {wb}"); } // Tier 4b: post-delta congruence checks (lean4lean isDefEqConst/Fvar/Proj) @@ -539,15 +537,15 @@ impl TypeChecker<'_, M> { // Tier 5 final-fail trace: when IX_DEF_EQ_TIER5_DUMP is set and the // pair's head names contain the configured substring, dump the // post-whnfCore wa/wb. This is where lazy-delta + Tier 4c gave up. - if let Ok(prefix) = std::env::var("IX_DEF_EQ_TIER5_DUMP") + if let Ok(prefix) = crate::env_var("IX_DEF_EQ_TIER5_DUMP") && let Ok(false) = result.as_ref() { let a_match = head_const_name(&wa).is_some_and(|n| n.contains(&prefix)); let b_match = head_const_name(&wb).is_some_and(|n| n.contains(&prefix)); if prefix.is_empty() || a_match || b_match { - eprintln!("[deq tier5 fail] depth={}", self.def_eq_depth); - eprintln!(" wa: {wa}"); - eprintln!(" wb: {wb}"); + log::info!("[deq tier5 fail] depth={}", self.def_eq_depth); + log::info!(" wa: {wa}"); + log::info!(" wb: {wb}"); } } @@ -807,7 +805,7 @@ impl TypeChecker<'_, M> { Ok(ty) => ty, Err(_) => return Ok(false), }; - if !self.is_prop_type(&a_ty)? { + if !self.is_prop_type(&a_ty) { return Ok(false); } let b_ty = match self.with_infer_only(|tc| tc.infer(b)) { @@ -826,14 +824,11 @@ impl TypeChecker<'_, M> { /// the inner chain are propagated as `Ok(false)` (treating ill-typed /// metadata as non-prop), matching the previous behaviour of /// `try_proof_irrel`. - pub(crate) fn is_prop_type( - &mut self, - ty: &KExpr, - ) -> Result> { + pub(crate) fn is_prop_type(&mut self, ty: &KExpr) -> bool { let cache_key = (ty.hash_key(), self.ctx_addr_for_lbr(ty.lbr())); if let Some(&cached) = self.env.is_prop_cache.get(&cache_key) { self.env.perf.record_is_prop_hit(); - return Ok(cached); + return cached; } self.env.perf.record_is_prop_miss(); self.record_hot_miss("is-prop", ty); @@ -852,7 +847,7 @@ impl TypeChecker<'_, M> { Err(_) => false, }; self.env.is_prop_cache.insert(cache_key, result); - Ok(result) + result } /// Unit-like type: non-recursive, 0 indices, 1 ctor with 0 fields. @@ -933,8 +928,8 @@ impl TypeChecker<'_, M> { if v.0 == num_bigint::BigUint::ZERO { return None; } - let pred = lean_ffi::nat::Nat(&v.0 - num_bigint::BigUint::from(1u64)); - let pred_addr = crate::ix::address::Address::hash(&pred.to_le_bytes()); + let pred = bignat::Nat(&v.0 - num_bigint::BigUint::from(1u64)); + let pred_addr = ix_common::address::Address::hash(&pred.to_le_bytes()); Some(self.env.intern.intern_expr(KExpr::nat(pred, pred_addr))) }, ExprData::App(f, arg, _) => match f.data() { @@ -1047,8 +1042,8 @@ impl TypeChecker<'_, M> { // Build list right-to-left: foldr let mut list = nil; for c in s.chars().rev() { - let nat_val = lean_ffi::nat::Nat::from(c as u64); - let nat_addr = crate::ix::address::Address::hash(&nat_val.to_le_bytes()); + let nat_val = bignat::Nat::from(c as u64); + let nat_addr = ix_common::address::Address::hash(&nat_val.to_le_bytes()); let nat_lit = self.intern(KExpr::nat(nat_val, nat_addr)); let char_val = self.intern(KExpr::app(char_of_nat.clone(), nat_lit)); let partial = self.intern(KExpr::app(cons.clone(), char_val)); @@ -1093,7 +1088,7 @@ impl TypeChecker<'_, M> { // Wrap s as λ(ty). s #0 let s_lifted = lift(&mut self.env.intern, s, 1, 0); let v0 = - self.intern(KExpr::var(0, M::meta_field(crate::ix::env::Name::anon()))); + self.intern(KExpr::var(0, M::meta_field(ix_common::env::Name::anon()))); let body = self.intern(KExpr::app(s_lifted, v0)); let s_lam = self.intern(KExpr::lam(name, bi, ty, body)); self.is_def_eq(t, &s_lam) @@ -1307,7 +1302,7 @@ impl TypeChecker<'_, M> { /// Check if a constant has Regular reducibility hints (not Abbrev or Opaque). /// Used to guard the same-head-spine optimization (lean4lean: dt.hints.isRegular). fn is_regular(&mut self, id: &KId) -> Result> { - use crate::ix::env::ReducibilityHints; + use ix_common::env::ReducibilityHints; Ok(matches!( self.try_get_const(id)?, Some(KConst::Defn { hints: ReducibilityHints::Regular(_), .. }) @@ -1329,7 +1324,7 @@ impl TypeChecker<'_, M> { /// - `Regular(h)` → `(1, h)` (ordered by height within the class) /// - `Abbrev` → `(2, 0)` (strictly greater than every `Regular(h)`) fn def_rank_id(&mut self, id: &KId) -> Result<(u8, u32), TcError> { - use crate::ix::env::ReducibilityHints; + use ix_common::env::ReducibilityHints; Ok(match self.try_get_const(id)? { Some(KConst::Defn { kind, hints, .. }) => match kind { DefKind::Opaque | DefKind::Theorem => (0, 0), @@ -1522,7 +1517,7 @@ impl TypeChecker<'_, M> { if !filter.is_empty() && !id_s.contains(filter) { return; } - eprintln!( + log::info!( "[proj-delta] const={} depth={} phase={} proj={}.{} a={} b={}", self.debug_label.as_deref().unwrap_or(""), self.def_eq_depth, @@ -1566,7 +1561,7 @@ impl TypeChecker<'_, M> { if !filter.is_empty() && !id_s.contains(filter) { return; } - eprintln!( + log::info!( "[eta] const={} depth={} reason={} id={} idx={} a={} b={}", self.debug_label.as_deref().unwrap_or(""), self.def_eq_depth, @@ -1696,17 +1691,21 @@ impl TypeChecker<'_, M> { { return; } - eprintln!( + log::info!( "[deq max] {kind} depth={} a_head={} b_head={} wa_head={} wb_head={}", - self.def_eq_depth, a_head, b_head, wa_head, wb_head + self.def_eq_depth, + a_head, + b_head, + wa_head, + wb_head ); - eprintln!(" a: {a}"); - eprintln!(" b: {b}"); + log::info!(" a: {a}"); + log::info!(" b: {b}"); if let Some(wa) = wa { - eprintln!(" wa: {wa}"); + log::info!(" wa: {wa}"); } if let Some(wb) = wb { - eprintln!(" wb: {wb}"); + log::info!(" wb: {wb}"); } } @@ -1725,7 +1724,7 @@ impl TypeChecker<'_, M> { { return; } - eprintln!( + log::info!( "[deq max] rec-fuel depth={} a={} b={}", self.def_eq_depth, compact_def_eq_expr(a), @@ -1744,9 +1743,9 @@ mod tests { use super::super::level::KUniv; use super::super::mode::{Anon, Meta}; use super::super::tc::TypeChecker; - use crate::ix::address::Address; - use crate::ix::env::{DataValue, DefinitionSafety, Name, ReducibilityHints}; - use crate::ix::ixon::constant::DefKind; + use ix_common::address::Address; + use ix_common::env::{DataValue, DefinitionSafety, Name, ReducibilityHints}; + use ixon::constant::DefKind; type AE = KExpr; type ME = KExpr; diff --git a/src/ix/kernel/env.rs b/crates/kernel/src/env.rs similarity index 96% rename from src/ix/kernel/env.rs rename to crates/kernel/src/env.rs index 1fdda019..f93a372e 100644 --- a/src/ix/kernel/env.rs +++ b/crates/kernel/src/env.rs @@ -11,7 +11,7 @@ use std::collections::BTreeSet; use rustc_hash::{FxHashMap, FxHashSet}; use std::cell::OnceCell; -use crate::ix::address::Address; +use ix_common::address::Address; use super::constant::{KConst, RecRule}; use super::error::TcError; @@ -307,6 +307,14 @@ pub struct KEnv { /// universe args). Mirrors lean4 C++ `m_unfold` cache. Cross-call sharing of /// universe-substituted bodies eliminates O(body) walks on every unfold. pub unfold_cache: FxHashMap>, + /// Memo of `try_reduce_nat_succ_iter` STUCK outcomes: succ-chain args + /// whose base never collapses to a literal. Keyed like `whnf_cache` + /// ((expr_hash, ctx_hash)). The succ-collapse loop runs its inner WHNF + /// in `NatSuccMode::Stuck`, which bypasses the WHNF caches, so without + /// this memo a stuck `Nat.succ^k(x)` chain is re-peeled from every + /// depth it is encountered at — O(k²) fuel for symbolic-plus-literal + /// Nat arithmetic (e.g. `x + 0xC0` in the UTF-8 codec proofs). + pub nat_succ_stuck: FxHashSet<(Addr, Addr)>, /// Ingress cache: LeanExpr → KExpr conversion results. /// Keyed by (expr_hash, param_names_hash) to account for different /// level param bindings producing different KExprs from the same LeanExpr. @@ -358,7 +366,7 @@ pub struct KEnv { /// worker; `None` (the default) has zero overhead. Deliberately preserved /// across `clear`/`clear_releasing_memory` so recording survives scheduled /// block boundaries within a run. - pub profile_sink: Option, + pub profile_sink: Option, } impl Default for KEnv { @@ -375,7 +383,7 @@ impl Drop for KEnv { if super::perf::enabled() { let summary = self.perf.summary(); if !summary.is_empty() { - eprint!("{summary}"); + log::info!("{summary}"); } } } @@ -405,6 +413,7 @@ impl KEnv { def_eq_cheap_cache: FxHashMap::default(), def_eq_failure: FxHashSet::default(), unfold_cache: FxHashMap::default(), + nat_succ_stuck: FxHashSet::default(), ingress_cache: FxHashMap::default(), is_prop_cache: FxHashMap::default(), recursor_cache: FxHashMap::default(), @@ -519,6 +528,7 @@ impl KEnv { self.def_eq_cheap_cache.clear(); self.def_eq_failure.clear(); self.unfold_cache.clear(); + self.nat_succ_stuck.clear(); self.ingress_cache.clear(); self.is_prop_cache.clear(); self.recursor_cache.clear(); @@ -580,6 +590,7 @@ impl KEnv { self.def_eq_cheap_cache = FxHashMap::default(); self.def_eq_failure = FxHashSet::default(); self.unfold_cache = FxHashMap::default(); + self.nat_succ_stuck = FxHashSet::default(); self.ingress_cache = FxHashMap::default(); self.is_prop_cache = FxHashMap::default(); self.recursor_cache = FxHashMap::default(); @@ -610,6 +621,7 @@ impl KEnv { self.def_eq_cheap_cache.clear(); self.def_eq_failure.clear(); self.unfold_cache.clear(); + self.nat_succ_stuck.clear(); self.is_prop_cache.clear(); } } @@ -619,7 +631,7 @@ mod tests { use super::super::mode::Anon; use super::super::primitive::PrimAddrs; use super::*; - use crate::ix::address::Address; + use ix_common::address::Address; fn mk_addr(s: &str) -> Address { Address::hash(s.as_bytes()) diff --git a/src/ix/kernel/equiv.rs b/crates/kernel/src/equiv.rs similarity index 100% rename from src/ix/kernel/equiv.rs rename to crates/kernel/src/equiv.rs diff --git a/src/ix/kernel/error.rs b/crates/kernel/src/error.rs similarity index 99% rename from src/ix/kernel/error.rs rename to crates/kernel/src/error.rs index 0d253436..44ad4852 100644 --- a/src/ix/kernel/error.rs +++ b/crates/kernel/src/error.rs @@ -2,7 +2,7 @@ use std::cmp::Ordering; -use crate::ix::address::Address; +use ix_common::address::Address; use super::expr::KExpr; use super::mode::KernelMode; diff --git a/src/ix/kernel/expr.rs b/crates/kernel/src/expr.rs similarity index 98% rename from src/ix/kernel/expr.rs rename to crates/kernel/src/expr.rs index 009bcf82..fe5ce40c 100644 --- a/src/ix/kernel/expr.rs +++ b/crates/kernel/src/expr.rs @@ -6,12 +6,12 @@ use std::fmt; use std::sync::Arc; -use crate::ix::address::Address; -use crate::ix::env::{ +use bignat::Nat; +use ix_common::address::Address; +use ix_common::env::{ BinderInfo, DataValue, EALL, EAPP, EFVAR, ELAM, ELET, ENAT, EPRJ, EREF, ESORT, ESTR, EVAR, Name, }; -use lean_ffi::nat::Nat; use super::env::Addr; use super::id::KId; @@ -48,7 +48,7 @@ pub struct ExprInfo { } /// Per-`TypeChecker` unique identifier for a free variable. Generated by -/// [`crate::ix::kernel::lctx::NameGenerator`] and embedded into the blake3 +/// [`crate::lctx::NameGenerator`] and embedded into the blake3 /// content hash of [`ExprData::FVar`] nodes, so that two distinct fvars hash /// distinctly. This is the soundness lever that lets cache keys be the /// expression hash alone (no separate local-context key) — see the kernel @@ -69,7 +69,7 @@ pub enum ExprData { /// Free variable: opaque identity from the active local context. /// `FVarId` participates in the content hash; the user-facing `Name` is /// preserved (in Meta mode) for diagnostics. The looked-up type lives in - /// the active [`crate::ix::kernel::lctx::LocalContext`], not on the node. + /// the active [`crate::lctx::LocalContext`], not on the node. FVar(FVarId, M::MField, ExprInfo), Sort(KUniv, ExprInfo), Const(KId, Box<[KUniv]>, ExprInfo), @@ -802,8 +802,8 @@ fn collect_spine(e: &KExpr) -> (KExpr, Vec>) { mod tests { use super::super::mode::{Anon, Meta}; use super::*; - use crate::ix::address::Address; - use crate::ix::env::BinderInfo; + use ix_common::address::Address; + use ix_common::env::BinderInfo; type ME = KExpr; type AE = KExpr; diff --git a/src/ix/kernel/id.rs b/crates/kernel/src/id.rs similarity index 98% rename from src/ix/kernel/id.rs rename to crates/kernel/src/id.rs index 621efdf3..36316984 100644 --- a/src/ix/kernel/id.rs +++ b/crates/kernel/src/id.rs @@ -1,8 +1,8 @@ use std::fmt; use std::hash::{Hash, Hasher}; -use crate::ix::address::Address; -use crate::ix::env::Name; +use ix_common::address::Address; +use ix_common::env::Name; use super::mode::{KernelMode, MetaDisplay, MetaHash}; diff --git a/src/ix/kernel/inductive.rs b/crates/kernel/src/inductive.rs similarity index 98% rename from src/ix/kernel/inductive.rs rename to crates/kernel/src/inductive.rs index 4cba8c1c..52e81028 100644 --- a/src/ix/kernel/inductive.rs +++ b/crates/kernel/src/inductive.rs @@ -4,9 +4,7 @@ //! constraints, return types) and generates canonical recursors following //! lean4lean's constructive approach, then compares with provided recursors. -use std::sync::LazyLock; - -use crate::ix::address::Address; +use ix_common::address::Address; use super::constant::KConst; use super::env::{GeneratedRecursor, RecursorAuxOrder}; @@ -23,14 +21,14 @@ use super::tc::{TypeChecker, collect_app_spine, expr_mentions_any_addr}; /// regime or a mutual block with near-identical peers triggers a fresh diff, /// turning a normal compile into a wall of stderr. Set `IX_TYPE_DIFF=1` to /// enable when investigating a specific mismatch. -static IX_TYPE_DIFF: LazyLock = - LazyLock::new(|| std::env::var("IX_TYPE_DIFF").is_ok()); +static IX_TYPE_DIFF: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_TYPE_DIFF").is_ok()); /// Emit nested-aux recursor ordering/selection diagnostics for names whose /// display form starts with the configured prefix. Example: /// `IX_RECURSOR_DUMP=Lean.Doc.Block`. -static IX_RECURSOR_DUMP: LazyLock> = LazyLock::new(|| { - std::env::var("IX_RECURSOR_DUMP").ok().filter(|s| !s.is_empty()) +static IX_RECURSOR_DUMP: crate::EnvString = crate::EnvString::new(|| { + crate::env_var("IX_RECURSOR_DUMP").ok().filter(|s| !s.is_empty()) }); /// A member of the "flat" mutual block used for recursor generation. @@ -496,7 +494,7 @@ impl TypeChecker<'_, M> { n_rec_params: u64, univ_offset: u64, ) -> Result>, TcError> { - let anon = || M::meta_field(crate::ix::env::Name::anon()); + let anon = || M::meta_field(ix_common::env::Name::anon()); let all_block_addrs: Vec
= block_inds.iter().map(|id| id.addr.clone()).collect(); @@ -919,7 +917,7 @@ impl TypeChecker<'_, M> { continue; } - let anon = || M::meta_field(crate::ix::env::Name::anon()); + let anon = || M::meta_field(ix_common::env::Name::anon()); let mut result = self.env.intern.intern_expr(KExpr::cnst( aux_ids[idx].clone(), block_us.to_vec().into_boxed_slice(), @@ -954,8 +952,8 @@ impl TypeChecker<'_, M> { n_block_params: u64, ) -> Result< Vec<( - M::MField, - M::MField, + M::MField, + M::MField, KExpr, )>, TcError, @@ -994,8 +992,8 @@ impl TypeChecker<'_, M> { &mut self, body: KExpr, binders: &[( - M::MField, - M::MField, + M::MField, + M::MField, KExpr, )], ) -> KExpr { @@ -1045,13 +1043,11 @@ impl TypeChecker<'_, M> { aux: &[FlatBlockMember], n_block_params: u64, block_us: &[KUniv], - all0_name: Option<&crate::ix::env::Name>, + all0_name: Option<&ix_common::env::Name>, block_first_id: Option<&KId>, ) -> Result, TcError> { - use crate::ix::env::Name; - use crate::ix::kernel::canonical_check::{ - KMutCtx, sort_kconsts_with_seed_key, - }; + use crate::canonical_check::{KMutCtx, sort_kconsts_with_seed_key}; + use ix_common::env::Name; use rustc_hash::FxHashMap; // Build synthetic Indc + Ctor views for each aux. @@ -1071,7 +1067,7 @@ impl TypeChecker<'_, M> { // the block's first inductive is unavailable, the wrap is empty (a no-op). let block_param_binders: Vec<( M::MField, - M::MField, + M::MField, KExpr, )> = match block_first_id { Some(id) if n_block_params > 0 => { @@ -1309,7 +1305,7 @@ impl TypeChecker<'_, M> { }); if dump_canonical { - eprintln!( + log::info!( "[canonical_aux_order.dump] all0={:?} n_aux={} n_block_params={}", all0_name.map(Name::pretty), pairs.len(), @@ -1317,7 +1313,7 @@ impl TypeChecker<'_, M> { ); for (i, (kid, kconst)) in pairs.iter().enumerate() { let seed = aux_seed_names.get(i).cloned().unwrap_or_else(Name::anon); - eprintln!( + log::info!( " pre-sort[{}] addr={} seed={} member_id_addr={}", i, &kid.addr.hex()[..8], @@ -1325,12 +1321,12 @@ impl TypeChecker<'_, M> { &aux[i].id.addr.hex()[..8] ); if let KConst::Indc { ty, ctors, .. } = kconst { - eprintln!(" indc.ty={ty}"); + log::info!(" indc.ty={ty}"); for (ci, ctor_kid) in ctors.iter().enumerate() { if let Some(KConst::Ctor { ty, .. }) = all_ctor_lookup.get(&ctor_kid.addr) { - eprintln!(" ctor[{ci}].ty={ty}"); + log::info!(" ctor[{ci}].ty={ty}"); } } } @@ -1349,10 +1345,10 @@ impl TypeChecker<'_, M> { )?; if dump_canonical { - eprintln!("[canonical_aux_order.dump] post-sort classes:"); + log::info!("[canonical_aux_order.dump] post-sort classes:"); for (ci, class) in classes.iter().enumerate() { for (mi, (kid, _)) in class.iter().enumerate() { - eprintln!(" class[{ci}][{mi}] addr={}", &kid.addr.hex()[..8]); + log::info!(" class[{ci}][{mi}] addr={}", &kid.addr.hex()[..8]); } } } @@ -1411,7 +1407,7 @@ impl TypeChecker<'_, M> { if !self.recursor_dump_matches_block(block_id, flat) { return; } - eprintln!( + log::info!( "[recursor.dump] {label} flat aux order for {block_id}: originals={} aux={}", n_originals, flat.len().saturating_sub(n_originals) @@ -1419,9 +1415,11 @@ impl TypeChecker<'_, M> { for (aux_i, member) in flat.iter().skip(n_originals).enumerate() { let spec = member.spec_params.iter().map(|e| format!("{e}")).collect::>(); - eprintln!( + log::info!( " aux[{aux_i:2}] id={} own_params={} indices={} spec={spec:?}", - member.id, member.own_params, member.n_indices + member.id, + member.own_params, + member.n_indices ); } } @@ -1532,18 +1530,18 @@ impl TypeChecker<'_, M> { failed_gen_major: Option<&KExpr>, failed_stored_major: Option<&KExpr>, ) { - eprintln!( + log::info!( "[recursor.align] FAIL ind_block={ind_block_id} rec_block={rec_block_id} \ peers={} flat={} rec_ids={} failed_gi={failed_gi}", generated_snapshot.len(), flat.len(), rec_ids.len() ); - eprintln!( + log::info!( " failed gen major: {}", Self::major_domain_signature_text(failed_gen_major) ); - eprintln!( + log::info!( " failed stored major: {}", Self::major_domain_signature_text(failed_stored_major) ); @@ -1573,18 +1571,18 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", None => None, }; let mark = if gi == failed_gi { "!!" } else { " " }; - eprintln!( + log::info!( " {mark} peer[{gi:2}] flat.id={} target={}… aux={} ind={}…", flat[gi].id, &target_addr.hex()[..8], flat[gi].is_aux, &gen_rec.ind_addr.hex()[..8] ); - eprintln!( + log::info!( " gen : {}", Self::major_domain_signature_text(gen_major.as_ref()) ); - eprintln!( + log::info!( " sto : {} (rid={})", Self::major_domain_signature_text(stored_major.as_ref()), rid @@ -1603,9 +1601,9 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", return Ok(false); } if depth > 80 { - eprintln!("[rule rhs diff] first diff {path}: recursion limit"); - eprintln!(" gen: {lhs}"); - eprintln!(" sto: {rhs}"); + log::info!("[rule rhs diff] first diff {path}: recursion limit"); + log::info!(" gen: {lhs}"); + log::info!(" sto: {rhs}"); return Ok(true); } @@ -1621,9 +1619,9 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", ExprData::All(_, _, rty, rbody, _), ) => { if !self.is_def_eq(lty, rty)? { - eprintln!("[rule rhs diff] first diff {path}.dom"); - eprintln!(" gen: {lty}"); - eprintln!(" sto: {rty}"); + log::info!("[rule rhs diff] first diff {path}.dom"); + log::info!(" gen: {lty}"); + log::info!(" sto: {rty}"); return Ok(true); } let saved = self.lctx.len(); @@ -1651,9 +1649,9 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", self.dump_rule_rhs_first_diff(la, ra, &format!("{path}.arg"), depth + 1) }, _ => { - eprintln!("[rule rhs diff] first diff {path}"); - eprintln!(" gen: {lw}"); - eprintln!(" sto: {rw}"); + log::info!("[rule rhs diff] first diff {path}"); + log::info!(" gen: {lw}"); + log::info!(" sto: {rw}"); Ok(true) }, } @@ -2028,7 +2026,7 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", } for (i, u) in us.iter().enumerate() { let expected = - KUniv::param(i as u64, M::meta_field(crate::ix::env::Name::anon())); + KUniv::param(i as u64, M::meta_field(ix_common::env::Name::anon())); if !univ_eq(u, &expected) { self.lctx.truncate(saved); return Err(TcError::Other(format!( @@ -2258,7 +2256,7 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", let is_large = self.is_large_eliminator(&result_level, &ind_infos)?; let univ_offset: u64 = if is_large { 1 } else { 0 }; let elim_level = if is_large { - KUniv::param(0, M::meta_field(crate::ix::env::Name::anon())) + KUniv::param(0, M::meta_field(ix_common::env::Name::anon())) } else { KUniv::zero() }; @@ -2295,7 +2293,7 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", block_first_id.as_ref(), )?; if self.recursor_dump_matches_block(block_id, &flat) { - eprintln!("[recursor.dump] canonical_order={canonical_order:?}"); + log::info!("[recursor.dump] canonical_order={canonical_order:?}"); } // Apply the permutation produced by sort_consts: each canonical // class index k maps to one representative aux from the original @@ -2395,7 +2393,7 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", let n_motives = flat.len() as u64; let n_minors: u64 = flat.iter().map(|m| m.ctors.len() as u64).sum(); let prefix_skip = n_params + n_motives + n_minors; - eprintln!( + log::info!( "[recursor.dump] generated recursors for {block_id}: count={} prefix_skip={prefix_skip}", generated.len() ); @@ -2405,7 +2403,7 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", prefix_skip, &g.ind_addr, )?; - eprintln!( + log::info!( " gen[{gi:2}] ind_addr={} {}", &g.ind_addr.hex()[..8], Self::major_domain_signature_text(major.as_ref()) @@ -2482,8 +2480,8 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", elim_level: &KUniv, _univ_offset: u64, ) -> Result, TcError> { - let anon = || M::meta_field(crate::ix::env::Name::anon()); - let bi_default = || M::meta_field(crate::ix::env::BinderInfo::Default); + let anon = || M::meta_field(ix_common::env::Name::anon()); + let bi_default = || M::meta_field(ix_common::env::BinderInfo::Default); // Get inductive type and instantiate with occurrence universe args // (concrete for auxiliaries, same as ind_us for originals). @@ -2616,8 +2614,8 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", }, }; let (ctor_ty_raw, _ctor_lvls) = ctor; - let anon = || M::meta_field(crate::ix::env::Name::anon()); - let bi_default = || M::meta_field(crate::ix::env::BinderInfo::Default); + let anon = || M::meta_field(ix_common::env::Name::anon()); + let bi_default = || M::meta_field(ix_common::env::BinderInfo::Default); let saved = self.lctx.len(); // Instantiate ctor type with occurrence universe args (concrete for output). @@ -2829,8 +2827,8 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", field_domains: &[KExpr], block_addrs: &[Address], ) -> Result, TcError> { - let anon = || M::meta_field(crate::ix::env::Name::anon()); - let bi_default = || M::meta_field(crate::ix::env::BinderInfo::Default); + let anon = || M::meta_field(ix_common::env::Name::anon()); + let bi_default = || M::meta_field(ix_common::env::BinderInfo::Default); // Lift the field domain from its original depth (minor_saved + field_idx) // to the current depth (minor_saved + n_fields + k). @@ -3043,8 +3041,8 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", let n_indices = u64_to_usize::(ind_infos[di].2)?; let block_addrs: Vec
= block_inds.iter().map(|id| id.addr.clone()).collect(); - let anon = || M::meta_field(crate::ix::env::Name::anon()); - let bi_default = || M::meta_field(crate::ix::env::BinderInfo::Default); + let anon = || M::meta_field(ix_common::env::Name::anon()); + let bi_default = || M::meta_field(ix_common::env::BinderInfo::Default); // Collect all binder domains in order: params, motives, minors, indices, major let mut domains: Vec> = Vec::new(); @@ -3212,7 +3210,7 @@ peers={} flat={} rec_ids={} failed_gi={failed_gi}", fn mk_ind_univs(&mut self, ind_lvls: u64, offset: u64) -> Box<[KUniv]> { (0..ind_lvls) .map(|i| { - KUniv::param(i + offset, M::meta_field(crate::ix::env::Name::anon())) + KUniv::param(i + offset, M::meta_field(ix_common::env::Name::anon())) }) .collect::>() .into_iter() @@ -3584,8 +3582,8 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", is_large: bool, _univ_offset: u64, ) -> Result, TcError> { - let anon = || M::meta_field(crate::ix::env::Name::anon()); - let bi_default = || M::meta_field(crate::ix::env::BinderInfo::Default); + let anon = || M::meta_field(ix_common::env::Name::anon()); + let bi_default = || M::meta_field(ix_common::env::BinderInfo::Default); let ctor_ty_raw = match self.get_const(ctor_id)? { KConst::Ctor { ty, .. } => ty.clone(), @@ -3852,8 +3850,8 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", is_large: bool, dom: &KExpr, ) -> Result, TcError> { - let anon = || M::meta_field(crate::ix::env::Name::anon()); - let bi_default = || M::meta_field(crate::ix::env::BinderInfo::Default); + let anon = || M::meta_field(ix_common::env::Name::anon()); + let bi_default = || M::meta_field(ix_common::env::BinderInfo::Default); let target_n_params = u64_to_usize::(flat[target_bi].own_params)?; @@ -3872,7 +3870,7 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", }, }; let rec_lvls: Box<[KUniv]> = (0..peer_rec_lvls) - .map(|i| KUniv::param(i, M::meta_field(crate::ix::env::Name::anon()))) + .map(|i| KUniv::param(i, M::meta_field(ix_common::env::Name::anon()))) .collect(); // Peel foralls from the domain to detect wrapping. @@ -4218,15 +4216,17 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", .or_else(|| generated.iter().position(|g| g.ind_addr == ind_id.addr)); if self.recursor_dump_matches_id(id) { - eprintln!( + log::info!( "[recursor.dump] check {} rec_block={} resolved_block={} stored_pos={stored_pos:?} selected_idx={selected_idx:?}", - id, rec_block, resolved_block + id, + rec_block, + resolved_block ); - eprintln!( + log::info!( "[recursor.dump] stored major: {}", Self::major_domain_signature_text(stored_major.as_ref()) ); - eprintln!("[recursor.dump] signature_matches={signature_matches:?}"); + log::info!("[recursor.dump] signature_matches={signature_matches:?}"); for (gi, g) in generated.iter().enumerate() { if g.ind_addr != ind_id.addr { continue; @@ -4236,7 +4236,7 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", prefix_skip, &g.ind_addr, )?; - eprintln!( + log::info!( " cand[{gi:2}] {}", Self::major_domain_signature_text(major.as_ref()) ); @@ -4289,11 +4289,11 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", } else { "idx/major" }; - eprintln!( + log::info!( "[type diff] binder {bi} ({label}) DIFFERS (p={params} m={motives} min={minors})" ); - eprintln!(" gen: {gd}"); - eprintln!(" sto: {sd}"); + log::info!(" gen: {gd}"); + log::info!(" sto: {sd}"); break; } let _ = self.push_fvar_decl_anon(gd.clone()); @@ -4302,9 +4302,9 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", bi += 1; }, _ => { - eprintln!("[type diff] return differs at {bi}"); - eprintln!(" gen: {gc}"); - eprintln!(" sto: {sc}"); + log::info!("[type diff] return differs at {bi}"); + log::info!(" gen: {gc}"); + log::info!(" sto: {sc}"); break; }, } @@ -4380,12 +4380,12 @@ re-run with `IX_RECURSOR_DUMP={}` for the full breakdown.", "rhs", 0, ); - eprintln!( + log::info!( "[rule rhs diff] rule {ri} RHS mismatch (fields={})", gen_rule.fields ); - eprintln!(" gen: {}", gen_rule.rhs); - eprintln!(" sto: {}", stored_rule.rhs); + log::info!(" gen: {}", gen_rule.rhs); + log::info!(" sto: {}", stored_rule.rhs); } return Err(TcError::Other(format!( "check_recursor: rule {ri} RHS mismatch" @@ -4505,7 +4505,7 @@ mod tests { use super::super::level::KUniv; use super::super::mode::Anon; use super::super::tc::TypeChecker; - use crate::ix::address::Address; + use ix_common::address::Address; type AE = KExpr; type AU = KUniv; diff --git a/src/ix/kernel/infer.rs b/crates/kernel/src/infer.rs similarity index 92% rename from src/ix/kernel/infer.rs rename to crates/kernel/src/infer.rs index 95f0232b..e65748eb 100644 --- a/src/ix/kernel/infer.rs +++ b/crates/kernel/src/infer.rs @@ -1,7 +1,5 @@ //! Type inference. -use std::sync::LazyLock; - use super::constant::KConst; use super::error::{TcError, u64_to_usize}; use super::expr::{ExprData, KExpr}; @@ -18,23 +16,23 @@ use super::tc::{TypeChecker, collect_app_spine}; /// drowning normal `FAIL` lines. Set `IX_APP_DIFF=1` when investigating /// why a specific `a_ty` and `dom` don't match after reduction. Pairs /// with the `a_ty` / `dom` pair already printed by the error display. -static IX_APP_DIFF: LazyLock = - LazyLock::new(|| std::env::var("IX_APP_DIFF").is_ok()); +static IX_APP_DIFF: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_APP_DIFF").is_ok()); /// Dump the full function/type/argument context when App inference fails /// because the inferred function type is not a forall. Off by default: these /// terms can be enormous in mathlib and hide the constant-level failure line. /// Set `IX_INFER_APP_FORALL_DUMP=1`, optionally with /// `IX_KERNEL_DEBUG_CONST=`, for targeted debugging. -static IX_INFER_APP_FORALL_DUMP: LazyLock = - LazyLock::new(|| std::env::var("IX_INFER_APP_FORALL_DUMP").is_ok()); +static IX_INFER_APP_FORALL_DUMP: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_INFER_APP_FORALL_DUMP").is_ok()); /// When set, log every 100K `infer` entries (total, across cache hits /// and real calls). A check using millions of infer calls points to a /// bloated term or a mis-firing cache. Pairs with `IX_DEF_EQ_COUNT_LOG` /// / `IX_WHNF_COUNT_LOG` for a full picture of per-check hotspots. -static IX_INFER_COUNT_LOG: LazyLock = - LazyLock::new(|| std::env::var("IX_INFER_COUNT_LOG").is_ok()); +static IX_INFER_COUNT_LOG: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_INFER_COUNT_LOG").is_ok()); static INFER_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); @@ -44,7 +42,7 @@ impl TypeChecker<'_, M> { if *IX_INFER_COUNT_LOG { let n = INFER_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); if n.is_multiple_of(100_000) && n > 0 { - eprintln!("[infer] count={n}"); + log::info!("[infer] count={n}"); } } let infer_only = self.infer_only; @@ -113,27 +111,27 @@ impl TypeChecker<'_, M> { let f_ty = self.infer(f)?; let (dom, cod) = self.ensure_forall(&f_ty).inspect_err(|_err| { if *IX_INFER_APP_FORALL_DUMP && self.debug_label_matches_env() { - eprintln!("[infer App] ensure_forall FAILED"); - eprintln!( + log::info!("[infer App] ensure_forall FAILED"); + log::info!( " const: {}", self.debug_label.as_deref().unwrap_or("") ); - eprintln!(" f: {f}"); - eprintln!(" f_ty: {f_ty}"); - eprintln!(" f_ty addr: {:?}", f_ty.addr()); - eprintln!(" a: {a}"); + log::info!(" f: {f}"); + log::info!(" f_ty: {f_ty}"); + log::info!(" f_ty addr: {:?}", f_ty.addr()); + log::info!(" a: {a}"); if let ExprData::App(ff, fa, _) = f.data() { - eprintln!(" ff: {ff}"); - eprintln!(" ff addr: {:?}", ff.addr()); + log::info!(" ff: {ff}"); + log::info!(" ff addr: {:?}", ff.addr()); if let Ok(ff_ty) = self.infer(ff) { - eprintln!(" ff_ty: {ff_ty}"); - eprintln!(" ff_ty addr: {:?}", ff_ty.addr()); + log::info!(" ff_ty: {ff_ty}"); + log::info!(" ff_ty addr: {:?}", ff_ty.addr()); if let Ok((dom2, cod2)) = self.ensure_forall(&ff_ty) { - eprintln!(" ff_ty dom: {dom2}"); - eprintln!(" ff_ty cod: {cod2}"); + log::info!(" ff_ty dom: {dom2}"); + log::info!(" ff_ty cod: {cod2}"); } } - eprintln!(" fa: {fa}"); + log::info!(" fa: {fa}"); } } })?; @@ -156,31 +154,31 @@ impl TypeChecker<'_, M> { // strategy. let a_whnf = self.whnf(&a_ty); let d_whnf = self.whnf(&dom); - let depth = std::env::var("IX_APP_DIFF_DEPTH") + let depth = crate::env_var("IX_APP_DIFF_DEPTH") .ok() .and_then(|s| s.parse::().ok()) .unwrap_or(2); - eprintln!( + log::info!( "[app diff] AppTypeMismatch at depth={}", self.ctx.len() ); - eprintln!(" f: {}", compact_expr(f)); - eprintln!(" a: {}", compact_expr(a)); - eprintln!(" a_ty: {}", compact_expr_deep(&a_ty, depth)); - eprintln!(" dom: {}", compact_expr_deep(&dom, depth)); - eprintln!(" a_ty data: {:?}", a_ty.data()); - eprintln!(" dom data: {:?}", dom.data()); + log::info!(" f: {}", compact_expr(f)); + log::info!(" a: {}", compact_expr(a)); + log::info!(" a_ty: {}", compact_expr_deep(&a_ty, depth)); + log::info!(" dom: {}", compact_expr_deep(&dom, depth)); + log::info!(" a_ty data: {:?}", a_ty.data()); + log::info!(" dom data: {:?}", dom.data()); match &a_whnf { Ok(w) => { - eprintln!(" a_ty whnf: {}", compact_expr_deep(w, depth)) + log::info!(" a_ty whnf: {}", compact_expr_deep(w, depth)) }, - Err(e) => eprintln!(" a_ty whnf: ERR {e}"), + Err(e) => log::info!(" a_ty whnf: ERR {e}"), } match &d_whnf { Ok(w) => { - eprintln!(" dom whnf: {}", compact_expr_deep(w, depth)) + log::info!(" dom whnf: {}", compact_expr_deep(w, depth)) }, - Err(e) => eprintln!(" dom whnf: ERR {e}"), + Err(e) => log::info!(" dom whnf: ERR {e}"), } } return Err(TcError::AppTypeMismatch { @@ -229,8 +227,8 @@ impl TypeChecker<'_, M> { abstract_fvars(&mut self.env.intern, &body_ty, &[fv_id]); self.lctx.truncate(saved); self.intern(KExpr::all( - M::meta_field(crate::ix::env::Name::anon()), - M::meta_field(crate::ix::env::BinderInfo::Default), + M::meta_field(ix_common::env::Name::anon()), + M::meta_field(ix_common::env::BinderInfo::Default), ty.clone(), abstracted, )) @@ -242,15 +240,15 @@ impl TypeChecker<'_, M> { let saved = self.lctx.len(); let fv_id = self.fresh_fvar_id(); let fv = self.intern(KExpr::fvar(fv_id, name.clone())); - if std::env::var("IX_FVAR_TRACE").is_ok() { - eprintln!( + if crate::env_var("IX_FVAR_TRACE").is_ok() { + log::info!( "[fvar All push] fv={fv_id} ty.addr={:?} ty.lbr={} ctx_len_before_push={} body.lbr={}", ty.addr(), ty.lbr(), self.ctx.len(), body.lbr(), ); - eprintln!(" ty data: {:?}", ty.data()); + log::info!(" ty data: {:?}", ty.data()); } self.lctx.push( fv_id, @@ -316,8 +314,8 @@ impl TypeChecker<'_, M> { self.infer_proj(&struct_id, *field, val, &val_ty)? }, - ExprData::Nat(..) => self.infer_nat_type()?, - ExprData::Str(..) => self.infer_str_type()?, + ExprData::Nat(..) => self.infer_nat_type(), + ExprData::Str(..) => self.infer_str_type(), }; if !infer_only { @@ -477,12 +475,12 @@ impl TypeChecker<'_, M> { } } - fn infer_nat_type(&mut self) -> Result, TcError> { - Ok(self.intern(KExpr::cnst(self.prims.nat.clone(), Box::new([])))) + fn infer_nat_type(&mut self) -> KExpr { + self.intern(KExpr::cnst(self.prims.nat.clone(), Box::new([]))) } - fn infer_str_type(&mut self) -> Result, TcError> { - Ok(self.intern(KExpr::cnst(self.prims.string.clone(), Box::new([])))) + fn infer_str_type(&mut self) -> KExpr { + self.intern(KExpr::cnst(self.prims.string.clone(), Box::new([]))) } fn inductive_app_is_prop( @@ -614,10 +612,10 @@ mod tests { use super::super::level::KUniv; use super::super::mode::Anon; use super::super::tc::TypeChecker; - use crate::ix::address::Address; - use crate::ix::env::{DefinitionSafety, ReducibilityHints}; - use crate::ix::ixon::constant::DefKind; - use lean_ffi::nat::Nat; + use bignat::Nat; + use ix_common::address::Address; + use ix_common::env::{DefinitionSafety, ReducibilityHints}; + use ixon::constant::DefKind; type AE = KExpr; type AU = KUniv; diff --git a/src/ix/kernel/ingress.rs b/crates/kernel/src/ingress.rs similarity index 93% rename from src/ix/kernel/ingress.rs rename to crates/kernel/src/ingress.rs index 38bedb6e..0b2a4e83 100644 --- a/src/ix/kernel/ingress.rs +++ b/crates/kernel/src/ingress.rs @@ -6,10 +6,12 @@ //! to avoid stack overflow on deeply nested expressions. use std::cell::Cell; +#[cfg(not(target_arch = "riscv64"))] use std::hash::{BuildHasher, Hash}; use std::sync::Arc; use std::time::{Duration, Instant}; +#[cfg(not(target_arch = "riscv64"))] use rayon::iter::{ IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, }; @@ -17,22 +19,27 @@ use rustc_hash::{FxHashMap, FxHashSet}; use dashmap::DashMap; -use crate::ix::address::Address; -use crate::ix::env::{ - BinderInfo, ConstantInfo as LeanCI, DefinitionSafety, Env as LeanEnv, Name, - ReducibilityHints, +use crate::env::Addr; +use bignat::Nat; +use ix_common::address::Address; +#[cfg(not(target_arch = "riscv64"))] +use ix_common::env::ConstantInfo as LeanCI; +#[cfg(not(target_arch = "riscv64"))] +use ix_common::env::DefinitionSafety; +#[cfg(not(target_arch = "riscv64"))] +use ix_common::env::Env as LeanEnv; +use ix_common::env::{BinderInfo, Name, ReducibilityHints}; +#[cfg(not(target_arch = "riscv64"))] +use ixon::constant::DefKind; +use ixon::constant::{ + Constant, ConstantInfo as IxonCI, MutConst as IxonMutConst, }; -use crate::ix::ixon::constant::{ - Constant, ConstantInfo as IxonCI, DefKind, MutConst as IxonMutConst, -}; -use crate::ix::ixon::env::Env as IxonEnv; -use crate::ix::ixon::expr::Expr as IxonExpr; -use crate::ix::ixon::metadata::{ +use ixon::env::Env as IxonEnv; +use ixon::expr::Expr as IxonExpr; +use ixon::metadata::{ ConstantMeta, ConstantMetaInfo, ExprMeta, ExprMetaData, resolve_kvmap, }; -use crate::ix::ixon::univ::Univ as IxonUniv; -use crate::ix::kernel::env::Addr; -use lean_ffi::nat::Nat; +use ixon::univ::Univ as IxonUniv; use super::constant::{KConst, RecRule}; use super::env::{InternTable, KEnv}; @@ -1372,7 +1379,7 @@ fn ingress_expr( #[allow(clippy::too_many_arguments)] fn ingress_defn( - def: &crate::ix::ixon::constant::Definition, + def: &ixon::constant::Definition, self_id: KId, meta: &ConstantMeta, ixon_env: &IxonEnv, @@ -1492,7 +1499,7 @@ fn ingress_defn( #[allow(clippy::too_many_arguments)] fn ingress_recursor( - rec: &crate::ix::ixon::constant::Recursor, + rec: &ixon::constant::Recursor, self_id: KId, meta: &ConstantMeta, ixon_env: &IxonEnv, @@ -1778,7 +1785,7 @@ fn ingress_standalone( #[allow(clippy::too_many_arguments)] fn ingress_muts_inductive( - ind: &crate::ix::ixon::constant::Inductive, + ind: &ixon::constant::Inductive, self_id: &KId, meta: &ConstantMeta, ixon_env: &IxonEnv, @@ -2085,9 +2092,11 @@ fn ingress_muts_block( let resolve_ctor = |cid: &KId| -> Option> { results_ref.iter().find(|(rid, _)| rid == cid).map(|(_, c)| c.clone()) }; - crate::ix::kernel::canonical_check::validate_canonical_block_single_pass::< - M, - >(entry_addr, &indcs, &resolve_ctor) + crate::canonical_check::validate_canonical_block_single_pass::( + entry_addr, + &indcs, + &resolve_ctor, + ) .map_err(|e| format!("{e}"))?; } @@ -2098,7 +2107,7 @@ fn ingress_muts_block( // Lightweight LeanExpr → KExpr ingress (compile-side) // ============================================================================ -use crate::ix::env::{ +use ix_common::env::{ Expr as LeanExpr, ExprData as LeanExprData, Level, LevelData, }; @@ -2483,7 +2492,7 @@ fn lean_expr_to_zexpr_raw( KExpr::prj_mdata(zid, idx.to_u64().unwrap_or(0), e_k, mdata_layers) }, LeanExprData::Lit(lit, _) => { - use crate::ix::env::Literal; + use ix_common::env::Literal; match lit { Literal::NatVal(n) => { // Address must match the Ixon-side blob address for this Nat, @@ -2659,6 +2668,7 @@ pub fn ingress_compiled_names( /// Returns `None` for variants without a mutual block (Axio, Quot, Ctor, Rec). /// Ctors/Recs have their own `induct`/`all` but the block identity comes /// from the inductive, which is what's on the map anyway. +#[cfg(not(target_arch = "riscv64"))] fn lean_constant_all(ci: &LeanCI) -> Option<&Vec> { match ci { LeanCI::DefnInfo(v) => Some(&v.all), @@ -2672,6 +2682,7 @@ fn lean_constant_all(ci: &LeanCI) -> Option<&Vec> { /// Look up position of `name` in its mutual `all` list, returning 0 for /// non-mutuals or constants not found in their own `all`. +#[cfg(not(target_arch = "riscv64"))] fn lean_member_idx(name: &Name, all: Option<&Vec>) -> u64 { all.and_then(|a| a.iter().position(|n| n == name)).map_or(0, |i| i as u64) } @@ -2691,6 +2702,7 @@ fn lean_member_idx(name: &Name, all: Option<&Vec>) -> u64 { /// (dangling refs, partial envs) fall through to `lean_name_to_addr` as a /// best-effort — those cases produce mismatched addresses and will surface /// as `UnknownConst` in the type checker rather than silently succeeding. +#[cfg(not(target_arch = "riscv64"))] pub fn build_leon_addr_map(lean_env: &LeanEnv) -> DashMap { // Build in parallel. Each shard's write lock is contended only when // distinct names happen to hash into the same shard — with 64 default @@ -2719,6 +2731,7 @@ pub fn build_leon_addr_map(lean_env: &LeanEnv) -> DashMap { /// well-formed Lean env should never trigger it. Callers that need /// strict resolution (e.g. "does this name exist?") should check /// `n2a.contains_key` directly. +#[cfg(not(target_arch = "riscv64"))] fn leon_addr_of(name: &Name, n2a: &DashMap) -> Address { n2a.get(name).map_or_else(|| lean_name_to_addr(name), |e| e.value().clone()) } @@ -2726,6 +2739,7 @@ fn leon_addr_of(name: &Name, n2a: &DashMap) -> Address { /// Build the `block` KId for a constant's mutual block. For singletons /// (no `all` or `all` length 1), the block id is the constant's own KId. /// For mutuals, it's the representative (first name in `all`). +#[cfg(not(target_arch = "riscv64"))] fn lean_block_id( self_name: &Name, all: Option<&Vec>, @@ -2736,6 +2750,7 @@ fn lean_block_id( } /// Build the `lean_all` KId list in Meta mode. +#[cfg(not(target_arch = "riscv64"))] fn lean_all_ids(all: &[Name], n2a: &DashMap) -> Vec> { all.iter().map(|n| KId::new(leon_addr_of(n, n2a), n.clone())).collect() } @@ -2744,6 +2759,7 @@ fn lean_all_ids(all: &[Name], n2a: &DashMap) -> Vec> { /// `lean_expr_to_zexpr_with_kenv` with the `n2a` map so inner `Const` /// references resolve to LEON addresses (same scheme used for the KId /// addresses in this constant's own fields). +#[cfg(not(target_arch = "riscv64"))] fn lean_const_to_kconst( self_name: &Name, ci: &LeanCI, @@ -2754,7 +2770,7 @@ fn lean_const_to_kconst( // LEON addressing so `Const` refs inside expressions resolve to the same // addresses we're using for KId keys — any KId we construct here and any // Const-ref we ingress agree on where they point. - let mut expr_to_k = |e: &crate::ix::env::Expr, pn: &[Name]| -> KExpr { + let mut expr_to_k = |e: &ix_common::env::Expr, pn: &[Name]| -> KExpr { lean_expr_to_zexpr_with_kenv(e, pn, kenv, Some(n2a), None) }; @@ -2937,9 +2953,10 @@ fn lean_const_to_kconst( /// **Meta-only**: the existing `lean_expr_to_zexpr_*` family is Meta-mode /// only, so this helper is Meta-mode only by extension. Generalizing to /// `Anon` would require generalizing `lean_expr_to_zexpr_raw` too. +#[cfg(not(target_arch = "riscv64"))] pub fn lean_ingress(lean_env: &LeanEnv) -> KEnv { use std::time::Instant; - let quiet = std::env::var("IX_QUIET").is_ok(); + let quiet = crate::env_var("IX_QUIET").is_ok(); let mut kenv = KEnv::::new_with_recursor_aux_order( super::env::RecursorAuxOrder::Source, ); @@ -2952,7 +2969,7 @@ pub fn lean_ingress(lean_env: &LeanEnv) -> KEnv { let t = Instant::now(); let n2a = build_leon_addr_map(lean_env); if !quiet { - eprintln!( + log::info!( "[lean_ingress] build_leon_addr_map: {:.2}s ({} names)", t.elapsed().as_secs_f32(), n2a.len() @@ -2967,7 +2984,7 @@ pub fn lean_ingress(lean_env: &LeanEnv) -> KEnv { kenv.insert(kid, kc); } if !quiet { - eprintln!( + log::info!( "[lean_ingress] pass 1 (serial ingress): {:.2}s", t.elapsed().as_secs_f32() ); @@ -3048,7 +3065,7 @@ pub fn lean_ingress(lean_env: &LeanEnv) -> KEnv { kenv.blocks.insert(block_id, members); } if !quiet { - eprintln!( + log::info!( "[lean_ingress] phase A (block seed): {:.2}s", t.elapsed().as_secs_f32() ); @@ -3082,7 +3099,7 @@ pub fn lean_ingress(lean_env: &LeanEnv) -> KEnv { } } if !quiet { - eprintln!( + log::info!( "[lean_ingress] phase B (ctor/rec append): {:.2}s", t.elapsed().as_secs_f32() ); @@ -3097,8 +3114,7 @@ pub fn lean_ingress(lean_env: &LeanEnv) -> KEnv { // Returns `Err` only if `prims()` has already been called on this // KEnv — fresh `KEnv::new()` above guarantees that hasn't happened, // so we ignore the Result. - let _ = kenv - .set_prims(crate::ix::kernel::primitive::Primitives::from_env_orig(&kenv)); + let _ = kenv.set_prims(crate::primitive::Primitives::from_env_orig(&kenv)); kenv } @@ -3458,6 +3474,7 @@ fn timed_drop_ns(value: T) -> u64 { /// (atomic refcount; the last decrementer destroys exactly once), and none /// of the value types have custom `Drop` impls — so this is a pure /// parallelisation of the existing teardown. +#[cfg(not(target_arch = "riscv64"))] fn timed_drop_dashmap_par(map: DashMap) -> u64 where K: Eq + Hash + Send, @@ -3475,6 +3492,7 @@ where /// a `Vec<(K, V)>` first (a cheap O(n) sequential pass that just moves owned /// pairs) and then `into_par_iter().for_each(drop)` on the Vec, letting /// rayon distribute the actual destructor work. +#[cfg(not(target_arch = "riscv64"))] fn timed_drop_fxmap_par(map: FxHashMap) -> u64 { let start = Instant::now(); let entries: Vec<(K, V)> = map.into_iter().collect(); @@ -3484,14 +3502,30 @@ fn timed_drop_fxmap_par(map: FxHashMap) -> u64 { /// Opt-out for the parallel drop path: set `IX_SEQ_IXON_DROP=1` to fall back /// to single-threaded `drop` for measurement comparisons. +#[cfg(not(target_arch = "riscv64"))] fn seq_ixon_drop_enabled() -> bool { - std::env::var_os("IX_SEQ_IXON_DROP").is_some() + crate::env_var_os("IX_SEQ_IXON_DROP").is_some() } +#[cfg(not(target_arch = "riscv64"))] +fn ingress_convert_stats_enabled() -> bool { + crate::env_var_os("IX_INGRESS_CONVERT_STATS").is_some() +} +#[cfg(target_arch = "riscv64")] fn ingress_convert_stats_enabled() -> bool { - std::env::var_os("IX_INGRESS_CONVERT_STATS").is_some() + false +} + +#[cfg(target_arch = "riscv64")] +fn drop_ingress_lookups( + _names: FxHashMap, + _name_to_addr: FxHashMap, + _quiet: bool, +) { + // Auto-dropped at end of scope. } +#[cfg(not(target_arch = "riscv64"))] fn drop_ingress_lookups( names: FxHashMap, name_to_addr: FxHashMap, @@ -3500,7 +3534,10 @@ fn drop_ingress_lookups( let total_start = Instant::now(); let names_len = names.len(); let name_to_addr_len = name_to_addr.len(); + #[cfg(not(target_arch = "riscv64"))] let sequential = seq_ixon_drop_enabled(); + #[cfg(target_arch = "riscv64")] + let sequential = true; // Drop the two lookup tables in series; each one fully utilises the rayon // pool internally via `timed_drop_fxmap_par`. Running them in parallel via @@ -3512,20 +3549,29 @@ fn drop_ingress_lookups( name_to_addr_ns: timed_drop_ns(name_to_addr), } } else { - LookupDropTiming { - names_ns: timed_drop_fxmap_par(names), - name_to_addr_ns: timed_drop_fxmap_par(name_to_addr), + #[cfg(not(target_arch = "riscv64"))] + { + LookupDropTiming { + names_ns: timed_drop_fxmap_par(names), + name_to_addr_ns: timed_drop_fxmap_par(name_to_addr), + } } + #[cfg(target_arch = "riscv64")] + unreachable!() }; let total_ns = elapsed_ns(total_start); if !quiet { - eprintln!( + #[cfg(not(target_arch = "riscv64"))] + let threads = rayon::current_num_threads(); + #[cfg(target_arch = "riscv64")] + let threads = 1; + log::info!( "[ixon_ingress] drop lookups: {:.2}s {} threads={} \ (names {:.2}s/{} name_to_addr {:.2}s/{})", seconds(total_ns), if sequential { "sequential" } else { "parallel" }, - rayon::current_num_threads(), + threads, seconds(timing.names_ns), names_len, seconds(timing.name_to_addr_ns), @@ -3540,17 +3586,25 @@ fn insert_standalone_entries( ) -> IngressInsertTiming { let mut timing = IngressInsertTiming::default(); + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); for (id, _) in &entries { zenv.blocks.entry(id.clone()).or_default().push(id.clone()); } - timing.blocks_ns = elapsed_ns(phase_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.blocks_ns = elapsed_ns(phase_start); + } + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); for (id, zc) in entries { zenv.insert(id, zc); } - timing.consts_ns = elapsed_ns(phase_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.consts_ns = elapsed_ns(phase_start); + } timing } @@ -3561,6 +3615,7 @@ fn insert_muts_entries( ) -> IngressInsertTiming { let mut timing = IngressInsertTiming::default(); + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); let block_id = entries.first().and_then(|(_, zc)| match zc { KConst::Defn { block, .. } @@ -3573,13 +3628,20 @@ fn insert_muts_entries( if let Some(bid) = block_id { zenv.blocks.insert(bid, member_ids); } - timing.blocks_ns = elapsed_ns(phase_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.blocks_ns = elapsed_ns(phase_start); + } + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); for (id, zc) in entries { zenv.insert(id, zc); } - timing.consts_ns = elapsed_ns(phase_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.consts_ns = elapsed_ns(phase_start); + } timing } @@ -3599,12 +3661,18 @@ pub fn ixon_ingress( pub fn ixon_ingress_owned( ixon_env: IxonEnv, ) -> Result<(KEnv, InternTable), String> { - let quiet = std::env::var_os("IX_QUIET").is_some(); + let quiet = crate::env_var_os("IX_QUIET").is_some(); let result = ixon_ingress_inner(&ixon_env); drop_ixon_env(ixon_env, quiet); result } +#[cfg(target_arch = "riscv64")] +fn drop_ixon_env(_ixon_env: IxonEnv, _quiet: bool) { + // Auto-dropped at end of scope. +} + +#[cfg(not(target_arch = "riscv64"))] fn drop_ixon_env(ixon_env: IxonEnv, quiet: bool) { let total_start = Instant::now(); // `anon_hints` is a small FxHashMap (one entry per Def from the .ixe's @@ -3623,7 +3691,10 @@ fn drop_ixon_env(ixon_env: IxonEnv, quiet: bool) { // which is single-threaded internally and dominates the total. Doing one // map at a time, fully parallel within, gives clean per-map timing and // saturates the rayon pool on the work that actually matters. + #[cfg(not(target_arch = "riscv64"))] let sequential = seq_ixon_drop_enabled(); + #[cfg(target_arch = "riscv64")] + let sequential = true; let timing = if sequential { IxonDropTiming { consts_ns: timed_drop_ns(consts), @@ -3633,23 +3704,32 @@ fn drop_ixon_env(ixon_env: IxonEnv, quiet: bool) { comms_ns: timed_drop_ns(comms), } } else { - IxonDropTiming { - consts_ns: timed_drop_dashmap_par(consts), - named_ns: timed_drop_dashmap_par(named), - names_ns: timed_drop_dashmap_par(names), - blobs_ns: timed_drop_dashmap_par(blobs), - comms_ns: timed_drop_dashmap_par(comms), + #[cfg(not(target_arch = "riscv64"))] + { + IxonDropTiming { + consts_ns: timed_drop_dashmap_par(consts), + named_ns: timed_drop_dashmap_par(named), + names_ns: timed_drop_dashmap_par(names), + blobs_ns: timed_drop_dashmap_par(blobs), + comms_ns: timed_drop_dashmap_par(comms), + } } + #[cfg(target_arch = "riscv64")] + unreachable!() }; let total_ns = elapsed_ns(total_start); if !quiet { - eprintln!( + #[cfg(not(target_arch = "riscv64"))] + let threads = rayon::current_num_threads(); + #[cfg(target_arch = "riscv64")] + let threads = 1; + log::info!( "[ixon_ingress] drop ixon_env: {:.2}s {} threads={} \ (consts {:.2}s/{} named {:.2}s/{} names {:.2}s/{} blobs {:.2}s/{} comms {:.2}s/{})", seconds(total_ns), if sequential { "sequential" } else { "parallel" }, - rayon::current_num_threads(), + threads, seconds(timing.consts_ns), consts_len, seconds(timing.named_ns), @@ -3667,22 +3747,23 @@ fn drop_ixon_env(ixon_env: IxonEnv, quiet: bool) { fn ixon_ingress_inner( ixon_env: &IxonEnv, ) -> Result<(KEnv, InternTable), String> { - let quiet = std::env::var_os("IX_QUIET").is_some(); + #[cfg(not(target_arch = "riscv64"))] let total_start = Instant::now(); + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); validate_no_reserved_marker_addresses(ixon_env)?; - if !quiet { - eprintln!( - "[ixon_ingress] validate_reserved: {:.2}s", - phase_start.elapsed().as_secs_f32() - ); - } + #[cfg(not(target_arch = "riscv64"))] + log::info!( + "[ixon_ingress] validate_reserved: {:.2}s", + phase_start.elapsed().as_secs_f32() + ); let mut intern = InternTable::new(); // Build the address → Lean-name lookup and the Lean-name → projection- // address lookup. See `build_ingress_lookups` for the role each plays. + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); let mut names: FxHashMap = FxHashMap::default(); for entry in ixon_env.names.iter() { @@ -3692,18 +3773,18 @@ fn ixon_ingress_inner( for entry in ixon_env.named.iter() { name_to_addr.insert(entry.key().clone(), entry.value().addr.clone()); } - if !quiet { - eprintln!( - "[ixon_ingress] build lookups: {:.2}s ({} names, {} named)", - phase_start.elapsed().as_secs_f32(), - names.len(), - name_to_addr.len() - ); - } + #[cfg(not(target_arch = "riscv64"))] + log::info!( + "[ixon_ingress] build lookups: {:.2}s ({} names, {} named)", + phase_start.elapsed().as_secs_f32(), + names.len(), + name_to_addr.len() + ); // Partition named entries into work items without cloning the `Named` // metadata payloads. Each worker resolves its current Named entry just // before conversion. + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); let mut work_items: Vec = Vec::new(); let mut standalone_count = 0usize; @@ -3750,17 +3831,17 @@ fn ixon_ingress_inner( }, } } - if !quiet { - eprintln!( - "[ixon_ingress] partition work: {:.2}s ({} standalone, {} muts)", - phase_start.elapsed().as_secs_f32(), - standalone_count, - muts_count - ); - } + #[cfg(not(target_arch = "riscv64"))] + log::info!( + "[ixon_ingress] partition work: {:.2}s ({} standalone, {} muts)", + phase_start.elapsed().as_secs_f32(), + standalone_count, + muts_count + ); // Convert each standalone constant or Muts block sequentially into the // single-threaded KEnv. + #[cfg(not(target_arch = "riscv64"))] let phase_start = Instant::now(); let convert_stats_enabled = ingress_convert_stats_enabled(); let mut zenv: KEnv = KEnv::new(); @@ -3771,26 +3852,38 @@ fn ixon_ingress_inner( match work_item { IngressWorkItem::Standalone(const_name) => { timing.standalone_items += 1; + #[cfg(not(target_arch = "riscv64"))] let lookup_start = Instant::now(); let named = ixon_env .lookup_name(&const_name) .ok_or_else(|| format!("{const_name}: missing Named entry"))?; - timing.lookup_ns += elapsed_ns(lookup_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.lookup_ns += elapsed_ns(lookup_start); + } + #[cfg(not(target_arch = "riscv64"))] let const_start = Instant::now(); let constant = match ixon_env.get_const(&named.addr) { Some(c) => { - timing.const_get_ns += elapsed_ns(const_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.const_get_ns += elapsed_ns(const_start); + } c }, None => { - timing.const_get_ns += elapsed_ns(const_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.const_get_ns += elapsed_ns(const_start); + } timing.missing_consts += 1; timing.convert_stats = convert_stats; stream = stream.merge(&timing); continue; }, }; + #[cfg(not(target_arch = "riscv64"))] let convert_start = Instant::now(); let entries = ingress_standalone( &const_name, @@ -3804,22 +3897,33 @@ fn ixon_ingress_inner( &mut convert_stats, ) .map_err(|e| format!("{const_name}: {e}"))?; - timing.convert_ns += elapsed_ns(convert_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.convert_ns += elapsed_ns(convert_start); + } timing.output_consts += entries.len() as u64; + #[cfg(not(target_arch = "riscv64"))] let insert_start = Instant::now(); let insert_timing = insert_standalone_entries(&mut zenv, entries); - timing.insert_ns += elapsed_ns(insert_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.insert_ns += elapsed_ns(insert_start); + } timing.insert_blocks_ns += insert_timing.blocks_ns; timing.insert_consts_ns += insert_timing.consts_ns; }, IngressWorkItem::Muts(entry_name) => { timing.muts_items += 1; + #[cfg(not(target_arch = "riscv64"))] let lookup_start = Instant::now(); let named = ixon_env .lookup_name(&entry_name) .ok_or_else(|| format!("{entry_name}: missing Named entry"))?; - timing.lookup_ns += elapsed_ns(lookup_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.lookup_ns += elapsed_ns(lookup_start); + } let all = match &named.meta.info { ConstantMetaInfo::Muts { all, .. } => all, @@ -3829,6 +3933,7 @@ fn ixon_ingress_inner( continue; }, }; + #[cfg(not(target_arch = "riscv64"))] let convert_start = Instant::now(); let entries = ingress_muts_block( &entry_name, @@ -3841,12 +3946,19 @@ fn ixon_ingress_inner( &mut convert_stats, ) .map_err(|e| format!("{entry_name}: {e}"))?; - timing.convert_ns += elapsed_ns(convert_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.convert_ns += elapsed_ns(convert_start); + } timing.output_consts += entries.len() as u64; + #[cfg(not(target_arch = "riscv64"))] let insert_start = Instant::now(); let insert_timing = insert_muts_entries(&mut zenv, entries); - timing.insert_ns += elapsed_ns(insert_start); + #[cfg(not(target_arch = "riscv64"))] + { + timing.insert_ns += elapsed_ns(insert_start); + } timing.insert_blocks_ns += insert_timing.blocks_ns; timing.insert_consts_ns += insert_timing.consts_ns; }, @@ -3854,107 +3966,110 @@ fn ixon_ingress_inner( timing.convert_stats = convert_stats; stream = stream.merge(&timing); } - if !quiet { - eprintln!( - "[ixon_ingress] stream ingress+insert: {:.2}s", - phase_start.elapsed().as_secs_f32() + #[cfg(not(target_arch = "riscv64"))] + log::info!( + "[ixon_ingress] stream ingress+insert: {:.2}s", + phase_start.elapsed().as_secs_f32() + ); + #[cfg(not(target_arch = "riscv64"))] + log::info!( + "[ixon_ingress] stream detail (worker-sum): lookup {:.2}s, const_get {:.2}s, convert {:.2}s, insert {:.2}s (blocks {:.2}s, consts {:.2}s), work {} standalone/{} muts, output {} consts, missing {}", + seconds(stream.lookup_ns), + seconds(stream.const_get_ns), + seconds(stream.convert_ns), + seconds(stream.insert_ns), + seconds(stream.insert_blocks_ns), + seconds(stream.insert_consts_ns), + stream.standalone_items, + stream.muts_items, + stream.output_consts, + stream.missing_consts + ); + #[cfg(not(target_arch = "riscv64"))] + let cs = &stream.convert_stats; + #[cfg(not(target_arch = "riscv64"))] + if cs.enabled { + let cache_lookups = cs.expr_cache_hits + cs.expr_cache_misses; + log::info!( + "[ixon_ingress] convert cache: roots {} process {} hits {} misses {} hit {:.1}% inserts {} peak {} clears {} cleared {} shares {}", + cs.expr_roots, + cs.expr_process, + cs.expr_cache_hits, + cs.expr_cache_misses, + percent(cs.expr_cache_hits, cache_lookups), + cs.expr_cache_inserts, + cs.expr_cache_peak, + cs.expr_cache_clears, + cs.expr_cache_entries_cleared, + cs.share_expansions ); - eprintln!( - "[ixon_ingress] stream detail (worker-sum): lookup {:.2}s, const_get {:.2}s, convert {:.2}s, insert {:.2}s (blocks {:.2}s, consts {:.2}s), work {} standalone/{} muts, output {} consts, missing {}", - seconds(stream.lookup_ns), - seconds(stream.const_get_ns), - seconds(stream.convert_ns), - seconds(stream.insert_ns), - seconds(stream.insert_blocks_ns), - seconds(stream.insert_consts_ns), - stream.standalone_items, - stream.muts_items, - stream.output_consts, - stream.missing_consts + log::info!( + "[ixon_ingress] convert nodes: sort {} var {} ref {} rec {} app {} lam {} all {} let {} prj {} str {} nat {} callsites {} args {}", + cs.sort_nodes, + cs.var_nodes, + cs.ref_nodes, + cs.rec_nodes, + cs.app_nodes, + cs.lam_nodes, + cs.all_nodes, + cs.let_nodes, + cs.prj_nodes, + cs.str_nodes, + cs.nat_nodes, + cs.callsites, + cs.callsite_args ); - let cs = &stream.convert_stats; - if cs.enabled { - let cache_lookups = cs.expr_cache_hits + cs.expr_cache_misses; - eprintln!( - "[ixon_ingress] convert cache: roots {} process {} hits {} misses {} hit {:.1}% inserts {} peak {} clears {} cleared {} shares {}", - cs.expr_roots, - cs.expr_process, - cs.expr_cache_hits, - cs.expr_cache_misses, - percent(cs.expr_cache_hits, cache_lookups), - cs.expr_cache_inserts, - cs.expr_cache_peak, - cs.expr_cache_clears, - cs.expr_cache_entries_cleared, - cs.share_expansions - ); - eprintln!( - "[ixon_ingress] convert nodes: sort {} var {} ref {} rec {} app {} lam {} all {} let {} prj {} str {} nat {} callsites {} args {}", - cs.sort_nodes, - cs.var_nodes, - cs.ref_nodes, - cs.rec_nodes, - cs.app_nodes, - cs.lam_nodes, - cs.all_nodes, - cs.let_nodes, - cs.prj_nodes, - cs.str_nodes, - cs.nat_nodes, - cs.callsites, - cs.callsite_args - ); - eprintln!( - "[ixon_ingress] convert metadata/univ: mdata_nodes {} mdata_kv_maps {} univ_roots {} univ_cache_hits {} univ_cache_misses {} univ_hit {:.1}% univ_cache_peak {} univ_process {} univ_interns {}", - cs.mdata_nodes, - cs.mdata_kv_maps, - cs.univ_roots, - cs.univ_cache_hits, - cs.univ_cache_misses, - percent(cs.univ_cache_hits, cs.univ_cache_hits + cs.univ_cache_misses), - cs.univ_cache_peak, - cs.univ_process, - cs.univ_interns - ); - let ie_lookups = cs.intern_expr_calls; - let iu_lookups = cs.intern_univ_calls; - eprintln!( - "[ixon_ingress] convert timing (worker-sum): \ - resolve_kvmap {:.2}s/{} arena_walk {:.2}s \ - intern_expr {:.2}s/{} (get_hits {:.1}%) \ - intern_univ {:.2}s/{} (get_hits {:.1}%) \ - expr_cache lookup {:.2}s / insert {:.2}s \ - get_blob {:.2}s/{} \ - kexpr_construct {:.2}s/{} \ - process_arm {:.2}s continuation_arms {:.2}s", - seconds(cs.resolve_kvmap_ns), - cs.resolve_kvmap_calls, - seconds(cs.arena_walk_ns), - seconds(cs.intern_expr_ns), - cs.intern_expr_calls, - percent(cs.intern_expr_get_hits, ie_lookups), - seconds(cs.intern_univ_ns), - cs.intern_univ_calls, - percent(cs.intern_univ_get_hits, iu_lookups), - seconds(cs.expr_cache_lookup_ns), - seconds(cs.expr_cache_insert_ns), - seconds(cs.get_blob_ns), - cs.get_blob_calls, - seconds(cs.kexpr_construct_ns), - cs.kexpr_construct_calls, - seconds(cs.process_arm_ns), - seconds(cs.continuation_arms_ns) - ); - } - eprintln!( - "[ixon_ingress] complete: {:.2}s ({} consts, {} blocks)", - total_start.elapsed().as_secs_f32(), - zenv.len(), - zenv.blocks.len() + log::info!( + "[ixon_ingress] convert metadata/univ: mdata_nodes {} mdata_kv_maps {} univ_roots {} univ_cache_hits {} univ_cache_misses {} univ_hit {:.1}% univ_cache_peak {} univ_process {} univ_interns {}", + cs.mdata_nodes, + cs.mdata_kv_maps, + cs.univ_roots, + cs.univ_cache_hits, + cs.univ_cache_misses, + percent(cs.univ_cache_hits, cs.univ_cache_hits + cs.univ_cache_misses), + cs.univ_cache_peak, + cs.univ_process, + cs.univ_interns + ); + let ie_lookups = cs.intern_expr_calls; + let iu_lookups = cs.intern_univ_calls; + log::info!( + "[ixon_ingress] convert timing (worker-sum): \ + resolve_kvmap {:.2}s/{} arena_walk {:.2}s \ + intern_expr {:.2}s/{} (get_hits {:.1}%) \ + intern_univ {:.2}s/{} (get_hits {:.1}%) \ + expr_cache lookup {:.2}s / insert {:.2}s \ + get_blob {:.2}s/{} \ + kexpr_construct {:.2}s/{} \ + process_arm {:.2}s continuation_arms {:.2}s", + seconds(cs.resolve_kvmap_ns), + cs.resolve_kvmap_calls, + seconds(cs.arena_walk_ns), + seconds(cs.intern_expr_ns), + cs.intern_expr_calls, + percent(cs.intern_expr_get_hits, ie_lookups), + seconds(cs.intern_univ_ns), + cs.intern_univ_calls, + percent(cs.intern_univ_get_hits, iu_lookups), + seconds(cs.expr_cache_lookup_ns), + seconds(cs.expr_cache_insert_ns), + seconds(cs.get_blob_ns), + cs.get_blob_calls, + seconds(cs.kexpr_construct_ns), + cs.kexpr_construct_calls, + seconds(cs.process_arm_ns), + seconds(cs.continuation_arms_ns) ); } + #[cfg(not(target_arch = "riscv64"))] + log::info!( + "[ixon_ingress] complete: {:.2}s ({} consts, {} blocks)", + total_start.elapsed().as_secs_f32(), + zenv.len(), + zenv.blocks.len() + ); - drop_ingress_lookups(names, name_to_addr, quiet); + drop_ingress_lookups(names, name_to_addr, false); Ok((zenv, intern)) } @@ -4014,7 +4129,7 @@ fn validate_no_reserved_marker_addresses( // discards `named`/`names`/`comms` sections. The helpers below do not // depend on those sections being empty — they simply never consult them. -use crate::ix::kernel::mode::Anon; +use crate::mode::Anon; /// Verify that a projection address computed from a block's structure /// is actually present in the env's consts. Wrapped here so the four @@ -4050,27 +4165,27 @@ fn verify_proj_addr_in_env( /// Deterministic IPrj content address for member `idx` of `block`. /// -/// Thin re-export of `crate::ix::ixon::constant::indc_proj_address` — +/// Thin re-export of `ixon::constant::indc_proj_address` — /// the canonical projection-address helper used by both compile and /// ingress paths. Keep the `anon_` alias so existing call sites read /// naturally in the anon-mode pipeline. pub fn anon_indc_proj_addr(block: &Address, idx: u64) -> Address { - crate::ix::ixon::constant::indc_proj_address(idx, block) + ixon::constant::indc_proj_address(idx, block) } /// Deterministic DPrj content address for member `idx` of `block`. pub fn anon_defn_proj_addr(block: &Address, idx: u64) -> Address { - crate::ix::ixon::constant::defn_proj_address(idx, block) + ixon::constant::defn_proj_address(idx, block) } /// Deterministic RPrj content address for member `idx` of `block`. pub fn anon_recr_proj_addr(block: &Address, idx: u64) -> Address { - crate::ix::ixon::constant::recr_proj_address(idx, block) + ixon::constant::recr_proj_address(idx, block) } /// Deterministic CPrj content address for ctor `(idx, cidx)` of `block`. pub fn anon_ctor_proj_addr(block: &Address, idx: u64, cidx: u64) -> Address { - crate::ix::ixon::constant::ctor_proj_address(idx, cidx, block) + ixon::constant::ctor_proj_address(idx, cidx, block) } /// Compute deterministic ctor projection addresses for every constructor of @@ -4078,7 +4193,7 @@ pub fn anon_ctor_proj_addr(block: &Address, idx: u64, cidx: u64) -> Address { fn anon_ctor_addrs( block_addr: &Address, indc_idx: u64, - ind: &crate::ix::ixon::constant::Inductive, + ind: &ixon::constant::Inductive, ) -> Vec
{ (0..ind.ctors.len() as u64) .map(|cidx| anon_ctor_proj_addr(block_addr, indc_idx, cidx)) @@ -4168,7 +4283,7 @@ fn ingress_anon_standalone( /// for the inductive and every ctor. #[allow(clippy::too_many_arguments)] fn ingress_anon_inductive( - ind: &crate::ix::ixon::constant::Inductive, + ind: &ixon::constant::Inductive, self_id: &KId, anon_env: &IxonEnv, block_constant: &Constant, @@ -4488,10 +4603,10 @@ pub fn ingress_anon_addr_shallow( #[cfg(test)] mod tests { use super::*; - use crate::ix::env::{self, BinderInfo}; - use crate::ix::ixon::metadata::CallSiteEntry; - use crate::ix::kernel::expr::ExprData; - use crate::ix::kernel::level::UnivData; + use crate::expr::ExprData; + use crate::level::UnivData; + use ix_common::env::{self, BinderInfo}; + use ixon::metadata::CallSiteEntry; fn mk_name(s: &str) -> Name { let mut n = Name::anon(); @@ -4646,10 +4761,10 @@ mod tests { #[test] fn ixon_ingress_rejects_reserved_marker_named_addr() { let env = IxonEnv::new(); - let marker = crate::ix::kernel::primitive::PrimAddrs::new().eager_reduce; + let marker = crate::primitive::PrimAddrs::new().eager_reduce; env.register_name( mk_name("Evil.marker"), - crate::ix::ixon::env::Named::with_addr(marker), + ixon::env::Named::with_addr(marker), ); let err = match ixon_ingress::(&env) { @@ -4663,15 +4778,13 @@ mod tests { #[test] fn ixon_ingress_rejects_reserved_marker_refs() { let env = IxonEnv::new(); - let marker = crate::ix::kernel::primitive::PrimAddrs::new().eager_reduce; + let marker = crate::primitive::PrimAddrs::new().eager_reduce; let constant = Constant::with_tables( - crate::ix::ixon::constant::ConstantInfo::Axio( - crate::ix::ixon::constant::Axiom { - is_unsafe: false, - lvls: 0, - typ: IxonExpr::sort(0), - }, - ), + ixon::constant::ConstantInfo::Axio(ixon::constant::Axiom { + is_unsafe: false, + lvls: 0, + typ: IxonExpr::sort(0), + }), vec![], vec![marker], vec![], @@ -5062,7 +5175,7 @@ mod tests { let list_addr = Address::hash(b"arbitrary"); ie.named.insert( list_name.clone(), - crate::ix::ixon::env::Named::with_addr(list_addr.clone()), + ixon::env::Named::with_addr(list_addr.clone()), ); let (name_map, addr_map) = build_ingress_lookups(&ie); @@ -5102,7 +5215,7 @@ mod tests { // the synthesized projection — that's the contract the rest of the // anon pipeline depends on (verifying the computed address against // the address actually stored in `env.consts`). - use crate::ix::ixon::constant::{ + use ixon::constant::{ Constant, ConstantInfo, ConstructorProj, DefinitionProj, InductiveProj, RecursorProj, }; diff --git a/src/ix/kernel/lctx.rs b/crates/kernel/src/lctx.rs similarity index 98% rename from src/ix/kernel/lctx.rs rename to crates/kernel/src/lctx.rs index 32c13347..d522e714 100644 --- a/src/ix/kernel/lctx.rs +++ b/crates/kernel/src/lctx.rs @@ -20,7 +20,7 @@ use rustc_hash::FxHashMap; -use crate::ix::env::{BinderInfo, Name}; +use ix_common::env::{BinderInfo, Name}; use super::env::InternTable; use super::expr::{ExprData, FVarId, KExpr}; @@ -254,8 +254,8 @@ pub fn is_fvar(e: &KExpr) -> bool { #[cfg(test)] mod tests { use super::*; - use crate::ix::kernel::level::KUniv; - use crate::ix::kernel::mode::Anon; + use crate::level::KUniv; + use crate::mode::Anon; type AE = KExpr; type AU = KUniv; diff --git a/src/ix/kernel/level.rs b/crates/kernel/src/level.rs similarity index 99% rename from src/ix/kernel/level.rs rename to crates/kernel/src/level.rs index 58d2b25d..0ff6df8c 100644 --- a/src/ix/kernel/level.rs +++ b/crates/kernel/src/level.rs @@ -37,7 +37,7 @@ use std::collections::BTreeMap; use std::fmt; use std::sync::Arc; -use crate::ix::env::{Name, UIMAX, UMAX, UPARAM, USUCC, UZERO}; +use ix_common::env::{Name, UIMAX, UMAX, UPARAM, USUCC, UZERO}; use super::env::Addr; use super::mode::{KernelMode, MetaDisplay}; @@ -708,7 +708,7 @@ pub fn univ_geq(u: &KUniv, v: &KUniv) -> bool { mod tests { use super::super::mode::{Anon, Meta}; use super::*; - use crate::ix::env::Name; + use ix_common::env::Name; type MU = KUniv; type AU = KUniv; diff --git a/crates/kernel/src/lib.rs b/crates/kernel/src/lib.rs new file mode 100644 index 00000000..488c47e9 --- /dev/null +++ b/crates/kernel/src/lib.rs @@ -0,0 +1,173 @@ +// Diagnostic env-var helpers. zkVM std targets (`target_os = "zkvm"` — Zisk, +// SP1, risc0, …) return `Ok` from `std::env::var` for any key (no real env +// in the guest), so every `IX_*` flag fires "on" by default and runs +// expensive diagnostic code paths whose output the guest can't even surface. +// These wrappers short-circuit to "not present" on any zkVM target and +// delegate to the real call elsewhere. +// +// Use these in place of `std::env::var` / `std::env::var_os` everywhere in +// the kernel. The Result / Option chains downstream (`.is_ok()`, `.ok()`, +// `.is_some()`, `.is_err()`, `match`, ...) all work identically. +#[inline] +pub(crate) fn env_var(name: &str) -> Result { + #[cfg(target_os = "zkvm")] + { + let _ = name; + Err(std::env::VarError::NotPresent) + } + #[cfg(not(target_os = "zkvm"))] + { + std::env::var(name) + } +} + +#[inline] +pub(crate) fn env_var_os(name: &str) -> Option { + #[cfg(target_os = "zkvm")] + { + let _ = name; + None + } + #[cfg(not(target_os = "zkvm"))] + { + std::env::var_os(name) + } +} + +// ============================================================================= +// LazyLock replacements for diagnostic env-var statics. +// +// On non-zkVM targets we want the existing thread-safe lazy-init behaviour +// (`std::sync::LazyLock`). On zkVM targets the initialiser would always +// produce a "not set" value (because `env_var` is hard-wired to `Err`), so +// `LazyLock`'s per-access atomic state load is pure overhead. These types +// collapse to a plain `bool` / `Option` field on zkVM and a real +// `LazyLock` everywhere else. Same `*FLAG` / `FLAG.as_ref()` call sites +// either way. +// ============================================================================= + +/// Boolean env-var flag (e.g. `IX_HOT_MISSES`). Compiles to `false` on zkVM. +pub(crate) struct EnvFlag { + #[cfg(not(target_os = "zkvm"))] + inner: std::sync::LazyLock bool>, + #[cfg(target_os = "zkvm")] + inner: bool, +} + +impl EnvFlag { + pub(crate) const fn new(_init: fn() -> bool) -> Self { + Self { + #[cfg(not(target_os = "zkvm"))] + inner: std::sync::LazyLock::new(_init), + #[cfg(target_os = "zkvm")] + inner: false, + } + } +} + +impl std::ops::Deref for EnvFlag { + type Target = bool; + #[inline] + fn deref(&self) -> &bool { + &self.inner + } +} + +/// `Option` env-var flag (e.g. `IX_DELTA_TRACE`). Compiles to +/// `None` on zkVM (so `IX_X.as_ref()` always returns `None` cheaply). +pub(crate) struct EnvString { + #[cfg(not(target_os = "zkvm"))] + inner: std::sync::LazyLock, fn() -> Option>, + #[cfg(target_os = "zkvm")] + inner: Option, +} + +impl EnvString { + pub(crate) const fn new(_init: fn() -> Option) -> Self { + Self { + #[cfg(not(target_os = "zkvm"))] + inner: std::sync::LazyLock::new(_init), + #[cfg(target_os = "zkvm")] + inner: None, + } + } +} + +impl std::ops::Deref for EnvString { + type Target = Option; + #[inline] + fn deref(&self) -> &Option { + &self.inner + } +} + +/// `Option` env-var flag (e.g. `IX_MAX_REC_FUEL`). Compiles to `None` +/// on zkVM. +pub(crate) struct EnvOptU64 { + #[cfg(not(target_os = "zkvm"))] + inner: std::sync::LazyLock, fn() -> Option>, + #[cfg(target_os = "zkvm")] + inner: Option, +} + +impl EnvOptU64 { + pub(crate) const fn new(_init: fn() -> Option) -> Self { + Self { + #[cfg(not(target_os = "zkvm"))] + inner: std::sync::LazyLock::new(_init), + #[cfg(target_os = "zkvm")] + inner: None, + } + } +} + +impl std::ops::Deref for EnvOptU64 { + type Target = Option; + #[inline] + fn deref(&self) -> &Option { + &self.inner + } +} + +pub mod anon_env; +pub mod anon_work; +pub mod canonical_check; +pub mod check; +pub mod claim; +pub mod congruence; +pub mod constant; +pub mod def_eq; +pub mod env; +pub mod equiv; +pub mod error; +pub mod expr; +pub mod id; +pub mod inductive; +pub mod infer; +pub mod ingress; +pub mod lctx; +pub mod level; +pub mod mode; +pub mod perf; +pub mod primitive; +// Sharding cost model + partitioner (out-of-circuit). `profile` records +// per-block heartbeats + the delta-unfold graph (the cost graph); `shard` +// partitions that graph into balanced, low-cross-ingress shards. Ported here +// from jcb/kernel-sharding (was the monolithic `crate::ix::{profile,shard}`): +// `profile` must live in the kernel crate because `KEnv` holds a `ProfileSink`. +// +// `profile` is dependency-light (hash maps only) so it compiles for the zkVM +// guest, where the `ProfileSink` field is simply always `None`. `shard` is the +// host-only partitioner — it uses rayon + `std::time` (gated to the same +// non-riscv targets that supply those deps), and the guest never partitions. +pub mod profile; +#[cfg(not(target_arch = "riscv64"))] +pub mod shard; +pub mod subst; +pub mod tc; +pub mod whnf; + +#[cfg(test)] +pub mod testing; +#[cfg(test)] +mod tutorial; diff --git a/src/ix/kernel/mode.rs b/crates/kernel/src/mode.rs similarity index 99% rename from src/ix/kernel/mode.rs rename to crates/kernel/src/mode.rs index 0477e8f1..cbaf1aa6 100644 --- a/src/ix/kernel/mode.rs +++ b/crates/kernel/src/mode.rs @@ -13,7 +13,7 @@ use std::fmt::{self, Debug}; use std::hash::Hash; -use crate::ix::env::{BinderInfo, DataValue, Name, NameData}; +use ix_common::env::{BinderInfo, DataValue, Name, NameData}; /// Serialize a metadata value into a `blake3::Hasher`. /// The `()` impl is a no-op, so erased metadata contributes nothing. @@ -44,7 +44,7 @@ impl MetaHash for BinderInfo { impl MetaHash for DataValue { fn meta_hash(&self, hasher: &mut blake3::Hasher) { - crate::ix::env::hash_data_value(self, hasher); + ix_common::env::hash_data_value(self, hasher); } } diff --git a/src/ix/kernel/perf.rs b/crates/kernel/src/perf.rs similarity index 86% rename from src/ix/kernel/perf.rs rename to crates/kernel/src/perf.rs index baf04e45..8f1bcf88 100644 --- a/src/ix/kernel/perf.rs +++ b/crates/kernel/src/perf.rs @@ -27,11 +27,10 @@ //! atomic op. use std::fmt; -use std::sync::LazyLock; use std::sync::atomic::{AtomicU64, Ordering}; -static PERF_ENABLED: LazyLock = - LazyLock::new(|| std::env::var_os("IX_PERF_COUNTERS").is_some()); +static PERF_ENABLED: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var_os("IX_PERF_COUNTERS").is_some()); /// Returns `true` iff `IX_PERF_COUNTERS` is set in the environment at the /// time this is first read. The result is cached for the lifetime of the @@ -301,6 +300,56 @@ impl PerfCounters { } } +// -- Reduction histograms (IX_REDUCE_HISTO) -------------------------------- +// +// Per-constant counts of delta unfolds and iota (recursor) reductions, +// process-global so a harness can run a single block and ask "which +// constants did the kernel grind on?". Gated separately from the cache +// counters because the DashMap entry bump is heavier than an atomic add. + +static REDUCE_HISTO_ENABLED: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var_os("IX_REDUCE_HISTO").is_some()); + +/// Returns `true` iff `IX_REDUCE_HISTO` is set in the environment. +#[inline] +pub fn reduce_histo_enabled() -> bool { + *REDUCE_HISTO_ENABLED +} + +/// Delta-unfold counts keyed by the unfolded constant's address. +pub static DELTA_HISTO: std::sync::LazyLock< + dashmap::DashMap, +> = std::sync::LazyLock::new(dashmap::DashMap::new); + +/// Iota-reduction counts keyed by the recursor's address. +pub static IOTA_HISTO: std::sync::LazyLock< + dashmap::DashMap, +> = std::sync::LazyLock::new(dashmap::DashMap::new); + +/// Count of `Nat.succ` peels performed by `try_reduce_nat_succ_iter`. +pub static NAT_SUCC_PEELS: AtomicU64 = AtomicU64::new(0); + +#[inline] +pub fn record_delta_histo(addr: &ix_common::address::Address) { + if reduce_histo_enabled() { + *DELTA_HISTO.entry(addr.clone()).or_insert(0) += 1; + } +} + +#[inline] +pub fn record_iota_histo(addr: &ix_common::address::Address) { + if reduce_histo_enabled() { + *IOTA_HISTO.entry(addr.clone()).or_insert(0) += 1; + } +} + +#[inline] +pub fn record_nat_succ_peel() { + if reduce_histo_enabled() { + NAT_SUCC_PEELS.fetch_add(1, Ordering::Relaxed); + } +} + fn write_rate( out: &mut impl fmt::Write, label: &str, diff --git a/src/ix/kernel/primitive.rs b/crates/kernel/src/primitive.rs similarity index 98% rename from src/ix/kernel/primitive.rs rename to crates/kernel/src/primitive.rs index 270ebea6..3ffa1c48 100644 --- a/src/ix/kernel/primitive.rs +++ b/crates/kernel/src/primitive.rs @@ -15,7 +15,7 @@ use std::sync::LazyLock; -use crate::ix::address::Address; +use ix_common::address::Address; use super::env::KEnv; use super::id::KId; @@ -1006,7 +1006,7 @@ impl Primitives { /// `@` fallbacks. pub fn from_addr_names(mut name_for_addr: F) -> Self where - F: FnMut(&Address) -> Option, + F: FnMut(&Address) -> Option, { Self::from_addrs_with(&PrimAddrs::new(), |addr| { name_for_addr(addr) @@ -1036,16 +1036,16 @@ impl Primitives { let mut r = |addr: &Address| -> KId { resolve(addr).unwrap_or_else(|| { let hex = addr.hex(); - let name = crate::ix::env::Name::str( - crate::ix::env::Name::anon(), + let name = ix_common::env::Name::str( + ix_common::env::Name::anon(), format!("@{}", &hex[..8]), ); KId::new(addr.clone(), M::meta_field(name)) }) }; let marker = |addr: &Address, marker_name: &str| -> KId { - let name = crate::ix::env::Name::str( - crate::ix::env::Name::anon(), + let name = ix_common::env::Name::str( + ix_common::env::Name::anon(), format!("@{marker_name}"), ); KId::new(addr.clone(), M::meta_field(name)) @@ -1158,12 +1158,12 @@ mod tests { use std::collections::HashMap; use super::*; - use crate::ix::env::Name; - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::expr::KExpr; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::level::KUniv; - use crate::ix::kernel::mode::Anon; + use crate::constant::KConst; + use crate::expr::KExpr; + use crate::id::KId; + use crate::level::KUniv; + use crate::mode::Anon; + use ix_common::env::Name; /// Collect every (field_name, addr) pair from `PrimAddrs` via reflection /// over a macro invocation at the caller — done here by an inline array. @@ -1360,7 +1360,7 @@ mod tests { // With an empty env, every `r(&a.*)` lookup misses and produces a // synthetic `@` KId. Confirm construction succeeds and // yields recognizable synthetic names (in Meta mode). - let env = KEnv::::new(); + let env = KEnv::::new(); let p = Primitives::from_env(&env); // The fallback name is `@`, a string part under an // anonymous Name. Verify the `nat` field lives at the expected @@ -1398,7 +1398,7 @@ mod tests { #[test] fn primitives_from_env_orig_uses_orig_addrs() { // from_env_orig uses PrimAddrs::new_orig (LEON addrs), not new(). - let env = KEnv::::new(); + let env = KEnv::::new(); let p = Primitives::from_env_orig(&env); let orig = PrimAddrs::new_orig(); let canon = PrimAddrs::new(); @@ -1413,7 +1413,7 @@ mod tests { // Check that the synthetic fallback name has the `@<8hex>` shape for // an address that doesn't exist in the env. Uses Meta mode so the // name metadata is observable. - let env = KEnv::::new(); + let env = KEnv::::new(); let p = Primitives::from_env_orig(&env); // Name of `p.nat` should be `@`. let orig = PrimAddrs::new_orig(); diff --git a/src/ix/profile.rs b/crates/kernel/src/profile.rs similarity index 99% rename from src/ix/profile.rs rename to crates/kernel/src/profile.rs index ed05c539..c12e062a 100644 --- a/src/ix/profile.rs +++ b/crates/kernel/src/profile.rs @@ -27,7 +27,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; -use crate::ix::address::Address; +use ix_common::address::Address; /// Magic bytes at the head of every `.ixesp` file. const MAGIC: &[u8; 8] = b"IXESP\0\0\0"; diff --git a/src/ix/shard.rs b/crates/kernel/src/shard.rs similarity index 76% rename from src/ix/shard.rs rename to crates/kernel/src/shard.rs index 0fd9682e..7996df90 100644 --- a/src/ix/shard.rs +++ b/crates/kernel/src/shard.rs @@ -58,8 +58,8 @@ use std::collections::BinaryHeap; use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering}; use std::time::Instant; -use crate::ix::address::Address; -use crate::ix::profile::BlockProfile; +use ix_common::address::Address; +use crate::profile::BlockProfile; /// Recurse the two halves of a bisection in parallel (rayon) when the parent /// sub-problem is at least this large; below it the join overhead isn't worth @@ -184,9 +184,23 @@ impl Hypergraph { /// the per-bisection balance tolerance (e.g. `0.05` for ±5%). `num_shards` /// need not be a power of two. pub fn partition(&self, num_shards: usize, epsilon: f64) -> Vec { + self.partition_with_tree(num_shards, epsilon).0 + } + + /// Like [`Self::partition`], but also returns the **bisection tree** — the + /// binary tree of min-cut splits whose leaves are the shard ids. Reusing this + /// as the proof-aggregation tree (rather than an arbitrary flat fold) + /// discharges each cross-shard assumption at the lowest common ancestor of the + /// shards that share it; the per-bisection min-cut means sibling subtrees have + /// the thinnest possible interface, so most discharge happens low in the tree. + pub fn partition_with_tree( + &self, + num_shards: usize, + epsilon: f64, + ) -> (Vec, AggNode) { let n = self.num_vertices(); if num_shards <= 1 { - return vec![0u32; n]; // everything in shard 0 + return (vec![0u32; n], AggNode::Leaf(0)); // everything in shard 0 } // Cap each block's balance weight at the ideal per-shard heartbeats // (total / num_shards). This keeps balancing heartbeat-aware while a balanced @@ -202,9 +216,152 @@ impl Hypergraph { // they can be partitioned on separate threads without their writes aliasing. let shard_of: Vec = (0..n).map(|_| AtomicU32::new(0)).collect(); let prog = PartitionProgress::new(num_shards); - rec_bisect(&sub, num_shards, 0, epsilon, &shard_of, &prog); + let tree = rec_bisect(&sub, num_shards, 0, epsilon, &shard_of, &prog); prog.done(); - shard_of.into_iter().map(AtomicU32::into_inner).collect() + let assignment = shard_of.into_iter().map(AtomicU32::into_inner).collect(); + (assignment, tree) + } +} + +// ============================================================================ +// Bisection / aggregation tree +// ============================================================================ + +/// The bisection tree produced by recursive min-cut partitioning: leaves are +/// shard ids, internal nodes are the two halves of a min-cut split. Reused as +/// the proof-aggregation tree so cross-shard assumptions discharge at the lowest +/// common ancestor of the shards that share them (see module docs and +/// [`agg_plan`]). Serialized into the `.ixes` manifest so the prover can fold +/// along it. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum AggNode { + /// A single shard, identified by its id. + Leaf(u32), + /// A min-cut split into a left and right subtree. + Internal(Box, Box), +} + +impl AggNode { + /// Number of shard leaves under this node. + pub fn num_leaves(&self) -> usize { + match self { + AggNode::Leaf(_) => 1, + AggNode::Internal(l, r) => l.num_leaves() + r.num_leaves(), + } + } + + /// The smallest shard id under this node — its left-to-right position. Used to + /// keep aggregation children in shard order (so the subject merkle-fold stays + /// the left-associative order the agg guest reproduces). + pub fn min_leaf(&self) -> u32 { + match self { + AggNode::Leaf(id) => *id, + AggNode::Internal(l, _) => l.min_leaf(), + } + } + + /// Prune to the leaves selected by `keep`: dropped leaves disappear and an + /// internal node that loses one child collapses to the survivor. Returns + /// `None` when nothing remains. Lets a prover fold along the tree even when + /// only a subset of shards was proven (empty shards, `--only-shard`). + pub fn prune(&self, keep: &impl Fn(u32) -> bool) -> Option { + match self { + AggNode::Leaf(id) => keep(*id).then_some(AggNode::Leaf(*id)), + AggNode::Internal(l, r) => match (l.prune(keep), r.prune(keep)) { + (Some(a), Some(b)) => Some(AggNode::Internal(Box::new(a), Box::new(b))), + (Some(a), None) | (None, Some(a)) => Some(a), + (None, None) => None, + }, + } + } + + /// Preorder serialization: `0u8, id(4)` for a leaf; `1u8, , ` for + /// an internal node. + fn put(&self, out: &mut Vec) { + match self { + AggNode::Leaf(id) => { + out.push(0); + out.extend_from_slice(&id.to_le_bytes()); + }, + AggNode::Internal(l, r) => { + out.push(1); + l.put(out); + r.put(out); + }, + } + } + + /// Inverse of [`Self::put`], reading from a cursor. + fn get(c: &mut Cur<'_>) -> Result { + match c.u8()? { + 0 => Ok(AggNode::Leaf(c.u32()?)), + 1 => { + let l = AggNode::get(c)?; + let r = AggNode::get(c)?; + Ok(AggNode::Internal(Box::new(l), Box::new(r))) + }, + t => Err(format!("bad AggNode tag {t}")), + } + } +} + +/// One step of an aggregation fold plan, in post order: every `Agg`'s child +/// indices refer to *earlier* entries in the plan, and the last entry is the +/// root. The prover materializes a slot per entry — `Leaf(id)` is shard `id`'s +/// leaf proof; `Agg(children)` folds those slots' proofs in one agg call. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum FoldOp { + Leaf(u32), + Agg(Vec), +} + +/// Lower the bisection tree to an arity-bounded fold plan. The binary tree is +/// *collapsed* so each agg call folds up to `arity` whole subtrees (never +/// splitting a subtree across calls), keeping the agg-proof count ~`N/(arity-1)` +/// — a strict binary fold would be ~`N` agg proofs, dominating cost. Children of +/// each agg are emitted in shard order so the subject merkle-fold matches the +/// guest's left-associative join. +pub fn agg_plan(tree: &AggNode, arity: usize) -> Vec { + let arity = arity.max(2); + let mut ops: Vec = Vec::new(); + build_plan(tree, arity, &mut ops); + ops +} + +/// Emit `node`'s plan entries; return the index of the entry representing it. +fn build_plan(node: &AggNode, arity: usize, ops: &mut Vec) -> usize { + match node { + AggNode::Leaf(id) => { + ops.push(FoldOp::Leaf(*id)); + ops.len() - 1 + }, + AggNode::Internal(l, r) => { + // Collapse the binary subtree into up to `arity` child subtrees: start + // from the two halves and repeatedly split the *largest* still-internal + // frontier node until we have `arity` children or all are leaves. This + // keeps tightly-coupled siblings together while bounding the fan-in. + let mut frontier: Vec<&AggNode> = vec![l, r]; + while frontier.len() < arity { + let largest = frontier + .iter() + .enumerate() + .filter(|(_, nd)| matches!(nd, AggNode::Internal(_, _))) + .max_by_key(|(_, nd)| nd.num_leaves()) + .map(|(i, _)| i); + let Some(i) = largest else { break }; // all leaves: cannot expand + let AggNode::Internal(l, r) = frontier.swap_remove(i) else { + unreachable!() + }; + frontier.push(l); + frontier.push(r); + } + // Shard order keeps the merkle subject-fold left-associative. + frontier.sort_by_key(|nd| nd.min_leaf()); + let child_idxs: Vec = + frontier.iter().map(|c| build_plan(c, arity, ops)).collect(); + ops.push(FoldOp::Agg(child_idxs)); + ops.len() - 1 + }, } } @@ -340,14 +497,14 @@ fn rec_bisect( epsilon: f64, shard_of: &[AtomicU32], prog: &PartitionProgress, -) { +) -> AggNode { if k <= 1 || sub.num_vertices() <= 1 { // A leaf (or a subtree with ≤1 vertex): everything here is one shard. for &g in &sub.global { shard_of[g as usize].store(base, Ordering::Relaxed); } prog.leaf(); - return; + return AggNode::Leaf(base); } prog.bisecting(sub.num_vertices(), k); let side = bisect(sub, epsilon); @@ -365,7 +522,7 @@ fn rec_bisect( shard_of[g as usize].store(base, Ordering::Relaxed); } prog.leaf(); - return; + return AggNode::Leaf(base); } // Allocate leaves ~proportional to heartbeat mass, clamped to [1, side size]. // `lo`/`hi` are feasible (lo ≤ hi) because nl + nr ≥ k with nl, nr ≥ 1. @@ -379,16 +536,21 @@ fn rec_bisect( let rbase = base + k_left as u32; // The two halves are independent (disjoint blocks) — recurse them in parallel // when the work is large enough to amortize the join. The result is identical - // to serial execution (each subtree is deterministic). - if nl + nr >= PARALLEL_THRESHOLD { + // to serial execution (each subtree is deterministic). Each call returns its + // subtree's `AggNode`; the two combine into this node's binary split — the + // bisection tree mirrors the recursion exactly. + let (ln, rn) = if nl + nr >= PARALLEL_THRESHOLD { rayon::join( || rec_bisect(&left, k_left, base, epsilon, shard_of, prog), || rec_bisect(&right, k - k_left, rbase, epsilon, shard_of, prog), - ); + ) } else { - rec_bisect(&left, k_left, base, epsilon, shard_of, prog); - rec_bisect(&right, k - k_left, rbase, epsilon, shard_of, prog); - } + ( + rec_bisect(&left, k_left, base, epsilon, shard_of, prog), + rec_bisect(&right, k - k_left, rbase, epsilon, shard_of, prog), + ) + }; + AggNode::Internal(Box::new(ln), Box::new(rn)) } /// Progress reporter for [`Hypergraph::partition`]. The partitioner is silent @@ -1082,6 +1244,10 @@ pub struct ShardManifest { pub shards: Vec, /// Total cross-shard ingress bytes (the km1 objective). pub total_cross_ingress: u128, + /// The bisection tree over the shard ids, for proof aggregation. `None` on + /// manifests written before this section existed (the prover then falls back + /// to a flat tree-fold). Set by [`Self::with_tree`]. + pub tree: Option, } impl ShardManifest { @@ -1139,9 +1305,18 @@ impl ShardManifest { num_shards: num_shards as u32, shards, total_cross_ingress: total_cross, + tree: None, } } + /// Attach the bisection tree (from [`Hypergraph::partition_with_tree`]) for + /// tree-aligned aggregation. + #[must_use] + pub fn with_tree(mut self, tree: AggNode) -> Self { + self.tree = Some(tree); + self + } + /// A human-readable what-if summary line. pub fn summary(&self) -> String { let hbs: Vec = self.shards.iter().map(|s| s.heartbeats).collect(); @@ -1203,6 +1378,16 @@ impl ShardManifest { put_addrs(&mut out, &sh.blocks); put_addrs(&mut out, &sh.foreign_blocks); } + // Trailing optional bisection-tree section: presence byte then preorder + // tree. Appended after the shards so older readers that stop at the shard + // count simply ignore it, and `from_bytes` treats end-of-input as `None`. + match &self.tree { + Some(t) => { + out.push(1); + t.put(&mut out); + }, + None => out.push(0), + } out } @@ -1233,10 +1418,18 @@ impl ShardManifest { assumption_root, }); } + // Optional trailing tree section. Absent (end-of-input) on pre-tree + // manifests, or an explicit `0` presence byte. + let tree = if c.pos < c.buf.len() { + if c.u8()? == 1 { Some(AggNode::get(&mut c)?) } else { None } + } else { + None + }; Ok(ShardManifest { num_shards: num_shards as u32, shards, total_cross_ingress, + tree, }) } } @@ -1304,11 +1497,12 @@ pub fn shard_esp( let profile = BlockProfile::from_bytes(&bytes) .map_err(|e| format!("parse {esp_path}: {e}"))?; let h = Hypergraph::from_profile(&profile); - let shard_of = h.partition(num_shards, balance); - let mut manifest = ShardManifest::build(&profile, &shard_of, num_shards); + let (shard_of, tree) = h.partition_with_tree(num_shards, balance); + let mut manifest = + ShardManifest::build(&profile, &shard_of, num_shards).with_tree(tree); for shard in &mut manifest.shards { shard.assumption_root = - crate::ix::ixon::merkle::merkle_root_canonical(&shard.foreign_blocks); + ixon::merkle::merkle_root_canonical(&shard.foreign_blocks); } if let Some(op) = out_path { std::fs::write(op, manifest.to_bytes()) @@ -1341,10 +1535,141 @@ pub fn shard_esp( )) } +/// The per-shard cycle cap implied by a machine's total RAM — so callers can +/// size shards straight from `MemTotal` without ever picking a budget. Inverts +/// the measured single-leaf prover model on this setup +/// (`peak_RAM_GB ≈ 45 + 32 × cycles_billions`) at ~78% of RAM (reserving the +/// rest for the OS + run-to-run variance). Returns 0 when the box can't even +/// hold the ~45 GB prover base (nothing will prove). Approximate by design — +/// pair with [`partition_for_cycle_cap`] to get N. +pub fn cycle_cap_for_ram(ram_gb: f64) -> u64 { + const BASE_GB: f64 = 45.0; // fixed prover witness/contribution buffers + const GB_PER_BCYCLE: f64 = 32.0; // RAM per billion guest cycles + const USABLE_FRAC: f64 = 0.78; // headroom for OS + variance + let headroom = ram_gb * USABLE_FRAC - BASE_GB; + if headroom <= 0.0 { + return 0; + } + (headroom / GB_PER_BCYCLE * 1e9) as u64 +} + +/// A partition sized to a per-shard Zisk **cycle** budget (rather than a fixed +/// shard count). See [`partition_for_cycle_cap`]. +pub struct BudgetPlan { + /// Chosen shard count. + pub num_shards: usize, + /// Shard assignment per block id (as [`Hypergraph::partition`] returns). + pub shard_of: Vec, + /// The bisection tree for the chosen partition, for tree-aligned aggregation. + pub tree: AggNode, + /// Per-shard heartbeat cap derived from the cycle cap + /// (`max_cycles / cycles_per_heartbeat`). + pub heartbeat_cap: u64, + /// Heaviest shard's heartbeats in the chosen partition. + pub max_shard_heartbeats: u64, + /// Largest single (atomic) block's heartbeats — the hard floor on + /// `max_shard_heartbeats` that no shard count can beat. + pub largest_block_heartbeats: u64, + /// True when the largest atomic block alone exceeds the cap: the budget is + /// infeasible by sharding (split that mutual block upstream, or raise the cap + /// / use a bigger box). + pub infeasible_atomic_floor: bool, +} + +/// Size a partition to a per-shard **cycle** budget, then partition. +/// +/// `max_cycles` is the ceiling on a single shard's in-circuit Zisk guest steps +/// — the leaf prover's trace size, which is what sets peak prover RAM. Convert +/// it from a host-RAM budget with the empirical single-leaf model measured on +/// this prover: +/// +/// ```text +/// peak_RAM_GB ≈ 45 + 32 × cycles_billions +/// ⇒ max_cycles ≈ (target_peak_GB − 45) / 32 × 1e9 +/// ``` +/// +/// e.g. a 256 GB box with a ~195 GB safe target (≈ 50 GB headroom for OS + +/// run-to-run variance) → `(195 − 45) / 32 ≈ 4.7` → `max_cycles ≈ 4.5e9`. +/// +/// `cycles_per_heartbeat` converts the planner's heartbeat balance metric to +/// guest cycles. Measured across 12 envs: large shardable envs cluster at +/// 194–208k whole-env, and the per-shard ratio runs ~5–8% higher (a shard +/// memoizes less) — mergesort's heaviest shard is ≈ 216k, so ~215k is the +/// conservative default for the regime that needs sharding. It is genuinely +/// workload-dependent though (tiny arithmetic envs ~130–160k; heavy-def-eq envs +/// like array/string-assoc ~258k), so recalibrate per environment with one +/// `--execute`: a shard's reported steps ÷ that shard's heartbeats. The cycle +/// cap's RAM headroom (target well under the wall) absorbs the residual error. +/// +/// Picks the smallest `N` whose heaviest shard fits `max_cycles / +/// cycles_per_heartbeat`, growing `N` proportionally to any overshoot and +/// re-partitioning (partitioning is milliseconds-to-seconds, negligible beside +/// proving). Stops at the **atomic-block floor**: a mutual block cannot be +/// split, so once the heaviest shard is pinned to the largest block, more shards +/// only worsen balance — `infeasible_atomic_floor` then flags that the cap is +/// unreachable and the block must be dealt with upstream. +pub fn partition_for_cycle_cap( + profile: &BlockProfile, + max_cycles: u64, + cycles_per_heartbeat: u64, + epsilon: f64, +) -> BudgetPlan { + let h = Hypergraph::from_profile(profile); + let hb_cap = (max_cycles / cycles_per_heartbeat.max(1)).max(1); + let largest_block = + profile.blocks().iter().map(|b| b.heartbeats).max().unwrap_or(0); + let total_hb = profile.total_heartbeats(); + let nblocks = profile.num_blocks().max(1); + + let max_shard_hb_of = |shard_of: &[u32], n: usize| -> u64 { + let mut sums = vec![0u64; n]; + for (b, &s) in shard_of.iter().enumerate() { + sums[s as usize] = + sums[s as usize].saturating_add(profile.block(b as u32).heartbeats); + } + sums.into_iter().max().unwrap_or(0) + }; + + // Initial estimate from the average load; refine against the real partition. + let mut n = ((total_hb / u128::from(hb_cap)).max(1) as usize).min(nblocks); + let (mut shard_of, mut tree) = h.partition_with_tree(n, epsilon); + let mut max_shard_hb = max_shard_hb_of(&shard_of, n); + + // Grow N until the heaviest shard fits the cap, or we hit the atomic-block + // floor / the block count. Proportional growth converges in a few re-cuts. + let mut guard = 0; + while max_shard_hb > hb_cap + && n < nblocks + && max_shard_hb > largest_block.saturating_mul(11) / 10 + && guard < 24 + { + // Next estimate: scale N by the overshoot ratio (so a 2× overshoot doubles + // N), but always advance by ≥1 to guarantee progress. Re-checking the real + // partition each round converges to the *minimal* N that fits. + let scaled = ((n as f64) * (max_shard_hb as f64 / hb_cap as f64)).ceil() as usize; + n = scaled.max(n + 1).min(nblocks); + let (so, t) = h.partition_with_tree(n, epsilon); + shard_of = so; + tree = t; + max_shard_hb = max_shard_hb_of(&shard_of, n); + guard += 1; + } + + BudgetPlan { + num_shards: n, + shard_of, + tree, + heartbeat_cap: hb_cap, + max_shard_heartbeats: max_shard_hb, + largest_block_heartbeats: largest_block, + infeasible_atomic_floor: largest_block > hb_cap, + } +} + #[cfg(test)] mod tests { use super::*; - use crate::ix::profile::ProfileBuilder; + use crate::profile::ProfileBuilder; fn addr(byte: u8) -> Address { Address::from_slice(&[byte; 32]).unwrap() @@ -1641,4 +1966,124 @@ mod tests { ); } } + + // ---- Bisection / aggregation tree ---- + + fn leaf(id: u32) -> AggNode { + AggNode::Leaf(id) + } + fn node(l: AggNode, r: AggNode) -> AggNode { + AggNode::Internal(Box::new(l), Box::new(r)) + } + + #[test] + fn partition_with_tree_leaves_match_shards() { + // 360 blocks → 4 shards. The tree's leaves must be exactly shard ids 0..4. + let p = two_big_clusters(180); + let h = Hypergraph::from_profile(&p); + let (shard_of, tree) = h.partition_with_tree(4, 0.10); + assert_eq!(tree.num_leaves(), 4); + let mut ids = Vec::new(); + fn collect(n: &AggNode, out: &mut Vec) { + match n { + AggNode::Leaf(id) => out.push(*id), + AggNode::Internal(l, r) => { + collect(l, out); + collect(r, out); + }, + } + } + collect(&tree, &mut ids); + ids.sort_unstable(); + assert_eq!(ids, vec![0, 1, 2, 3]); + // Every shard id assigned to some block must appear as a leaf. + let used: std::collections::BTreeSet = + shard_of.iter().copied().collect(); + assert!(used.iter().all(|s| ids.contains(s))); + } + + #[test] + fn agg_plan_arity_and_coverage() { + // Balanced 8-leaf tree: ((0 1)(2 3)) ((4 5)(6 7)). + let t = node( + node(node(leaf(0), leaf(1)), node(leaf(2), leaf(3))), + node(node(leaf(4), leaf(5)), node(leaf(6), leaf(7))), + ); + for arity in [2usize, 3, 4, 8] { + let plan = agg_plan(&t, arity); + // Every Agg has 2..=arity children; the last op is the root Agg. + let mut seen_leaves: Vec = Vec::new(); + for op in &plan { + match op { + FoldOp::Leaf(id) => seen_leaves.push(*id), + FoldOp::Agg(ch) => { + assert!(ch.len() >= 2 && ch.len() <= arity, "arity {arity}: {ch:?}"); + // children reference earlier entries (post order) + assert!(ch.iter().all(|&i| i < plan.len())); + }, + } + } + assert!(matches!(plan.last(), Some(FoldOp::Agg(_)))); + seen_leaves.sort_unstable(); + assert_eq!(seen_leaves, (0..8).collect::>(), "arity {arity}"); + } + } + + #[test] + fn agg_plan_children_in_shard_order() { + // Children of each agg must be emitted in increasing min-leaf order so the + // subject merkle-fold stays left-associative. + let t = node(node(leaf(0), leaf(1)), node(leaf(2), leaf(3))); + let plan = agg_plan(&t, 2); + // Root folds two subtrees; the left subtree's leaves precede the right's. + if let Some(FoldOp::Agg(ch)) = plan.last() { + // Map each child slot to its min leaf and assert ascending. + let mins: Vec = ch + .iter() + .map(|&i| match &plan[i] { + FoldOp::Leaf(id) => *id, + FoldOp::Agg(g) => g + .iter() + .map(|&j| if let FoldOp::Leaf(x) = &plan[j] { *x } else { u32::MAX }) + .min() + .unwrap_or(u32::MAX), + }) + .collect(); + let mut sorted = mins.clone(); + sorted.sort_unstable(); + assert_eq!(mins, sorted); + } else { + panic!("root must be an Agg"); + } + } + + #[test] + fn prune_collapses_and_preserves() { + // ((0 1)(2 3)): pruning leaf 1 collapses its parent to leaf 0; pruning a + // whole side collapses the root; keep-all is identity; keep-none is None. + let t = node(node(leaf(0), leaf(1)), node(leaf(2), leaf(3))); + assert_eq!(t.prune(&|_| true), Some(t.clone())); + assert_eq!(t.prune(&|_| false), None); + assert_eq!( + t.prune(&|id| id != 1), + Some(node(leaf(0), node(leaf(2), leaf(3)))) + ); + assert_eq!(t.prune(&|id| id >= 2), Some(node(leaf(2), leaf(3)))); + assert_eq!(t.prune(&|id| id == 3), Some(leaf(3))); + } + + #[test] + fn manifest_tree_roundtrip() { + let p = two_clusters(); + let h = Hypergraph::from_profile(&p); + let (shard_of, tree) = h.partition_with_tree(2, 0.10); + let m = ShardManifest::build(&p, &shard_of, 2).with_tree(tree.clone()); + let bytes = m.to_bytes(); + let q = ShardManifest::from_bytes(&bytes).unwrap(); + assert_eq!(q.tree, Some(tree)); + // A pre-tree manifest (tree = None) still roundtrips. + let m0 = ShardManifest::build(&p, &shard_of, 2); + let q0 = ShardManifest::from_bytes(&m0.to_bytes()).unwrap(); + assert_eq!(q0.tree, None); + } } diff --git a/src/ix/kernel/subst.rs b/crates/kernel/src/subst.rs similarity index 98% rename from src/ix/kernel/subst.rs rename to crates/kernel/src/subst.rs index 04a7dbaf..11ccac4a 100644 --- a/src/ix/kernel/subst.rs +++ b/crates/kernel/src/subst.rs @@ -11,8 +11,6 @@ //! uses a `PtrMap Expr Expr` for the same reason (see //! `refs/lean4lean/Lean4Lean/Expr.lean:14`). -use std::sync::LazyLock; - use rustc_hash::FxHashMap; use super::env::{Addr, InternTable}; @@ -25,8 +23,8 @@ use super::mode::KernelMode; /// seconds per infer call likely has substs dominating. The counter /// only fires for the top-level `subst` entry, so recursive sub-calls /// don't inflate the number. -static IX_SUBST_COUNT_LOG: LazyLock = - LazyLock::new(|| std::env::var("IX_SUBST_COUNT_LOG").is_ok()); +static IX_SUBST_COUNT_LOG: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_SUBST_COUNT_LOG").is_ok()); static SUBST_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); @@ -53,7 +51,7 @@ pub fn subst( if *IX_SUBST_COUNT_LOG && depth == 0 { let n = SUBST_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); if n.is_multiple_of(100_000) && n > 0 { - eprintln!("[subst] count={n}"); + log::info!("[subst] count={n}"); } } // Fast path: no loose bound vars at or below `depth` means nothing to @@ -281,7 +279,7 @@ fn simul_subst_cached( cache.insert(key, r.clone()); return r; } else if i >= depth + n { - KExpr::var(i - n, M::meta_field(crate::ix::env::Name::anon())) + KExpr::var(i - n, M::meta_field(ix_common::env::Name::anon())) } else { let r = body.clone(); cache.insert(key, r.clone()); @@ -661,7 +659,7 @@ fn instantiate_rev_cached( return r; } else if i >= depth + n { // Free variable above the instantiated range: shift down by `n`. - KExpr::var(i - n, M::meta_field(crate::ix::env::Name::anon())) + KExpr::var(i - n, M::meta_field(ix_common::env::Name::anon())) } else { // i < depth: bound by an inner binder we walked under; unchanged. let r = body.clone(); @@ -780,7 +778,7 @@ fn abstract_fvars_cached( // pass through unchanged (they belong to outer abstractions). if let Some(&p) = pos.get(id) { let new_var = - KExpr::var(depth + p, M::meta_field(crate::ix::env::Name::anon())); + KExpr::var(depth + p, M::meta_field(ix_common::env::Name::anon())); let interned = env.intern_expr(new_var); cache.insert(key, interned.clone()); return interned; @@ -874,11 +872,11 @@ impl ExprData { #[cfg(test)] mod tests { use super::*; - use crate::ix::address::Address; - use crate::ix::kernel::id::KId; - use crate::ix::kernel::level::KUniv; - use crate::ix::kernel::mode::Anon; - use lean_ffi::nat::Nat; + use crate::id::KId; + use crate::level::KUniv; + use crate::mode::Anon; + use bignat::Nat; + use ix_common::address::Address; type AE = KExpr; diff --git a/src/ix/kernel/tc.rs b/crates/kernel/src/tc.rs similarity index 97% rename from src/ix/kernel/tc.rs rename to crates/kernel/src/tc.rs index 3cccfa8d..257761f8 100644 --- a/src/ix/kernel/tc.rs +++ b/crates/kernel/src/tc.rs @@ -6,13 +6,11 @@ //! WHNF, type inference, def-eq, and constant checking are in separate modules //! that add `impl TypeChecker` blocks. -use std::sync::LazyLock; - use rustc_hash::FxHashMap; use rustc_hash::FxHashSet; -use crate::ix::address::Address; -use crate::ix::ixon::env::Env as IxonEnv; +use ix_common::address::Address; +use ixon::env::Env as IxonEnv; use super::constant::{KConst, RecRule}; use super::env::{Addr, KEnv}; @@ -58,15 +56,15 @@ pub const MAX_DEF_EQ_DEPTH: u32 = 2_000; /// for bisecting suspected loops. pub const MAX_REC_FUEL: u64 = 10_000_000; -static IX_MAX_REC_FUEL: LazyLock> = LazyLock::new(|| { - std::env::var("IX_MAX_REC_FUEL").ok().and_then(|s| s.parse().ok()) +static IX_MAX_REC_FUEL: crate::EnvOptU64 = crate::EnvOptU64::new(|| { + crate::env_var("IX_MAX_REC_FUEL").ok().and_then(|s| s.parse().ok()) }); -static IX_HOT_MISSES: LazyLock = - LazyLock::new(|| std::env::var("IX_HOT_MISSES").is_ok()); +static IX_HOT_MISSES: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_HOT_MISSES").is_ok()); -static IX_HOT_MISS_CTX: LazyLock = - LazyLock::new(|| std::env::var("IX_HOT_MISS_CTX").is_ok()); +static IX_HOT_MISS_CTX: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_HOT_MISS_CTX").is_ok()); pub fn max_rec_fuel() -> u64 { (*IX_MAX_REC_FUEL).unwrap_or(MAX_REC_FUEL) @@ -538,8 +536,8 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { /// the binder scope. pub fn open_binder( &mut self, - name: M::MField, - bi: M::MField, + name: M::MField, + bi: M::MField, ty: KExpr, body: &KExpr, ) -> (KExpr, FVarId) { @@ -559,8 +557,8 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { ty: KExpr, body: &KExpr, ) -> (KExpr, FVarId) { - let name = M::meta_field(crate::ix::env::Name::anon()); - let bi = M::meta_field(crate::ix::env::BinderInfo::Default); + let name = M::meta_field(ix_common::env::Name::anon()); + let bi = M::meta_field(ix_common::env::BinderInfo::Default); self.open_binder(name, bi, ty, body) } @@ -569,8 +567,8 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { /// abstract_fvars / structural identity comparisons). pub fn open_binder_with_fv( &mut self, - name: M::MField, - bi: M::MField, + name: M::MField, + bi: M::MField, ty: KExpr, body: &KExpr, ) -> (KExpr, KExpr, FVarId) { @@ -588,8 +586,8 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { ty: KExpr, body: &KExpr, ) -> (KExpr, KExpr, FVarId) { - let name = M::meta_field(crate::ix::env::Name::anon()); - let bi = M::meta_field(crate::ix::env::BinderInfo::Default); + let name = M::meta_field(ix_common::env::Name::anon()); + let bi = M::meta_field(ix_common::env::BinderInfo::Default); self.open_binder_with_fv(name, bi, ty, body) } @@ -599,7 +597,7 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { /// for downstream WHNF zeta-reduction). pub fn open_let( &mut self, - name: M::MField, + name: M::MField, ty: KExpr, val: KExpr, body: &KExpr, @@ -617,8 +615,8 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { /// later or in parallel). Returns the fvar id and the interned fvar /// expression. pub fn push_fvar_decl_anon(&mut self, ty: KExpr) -> (FVarId, KExpr) { - let name = M::meta_field(crate::ix::env::Name::anon()); - let bi = M::meta_field(crate::ix::env::BinderInfo::Default); + let name = M::meta_field(ix_common::env::Name::anon()); + let bi = M::meta_field(ix_common::env::BinderInfo::Default); let fv_id = self.fresh_fvar_id(); let fv = self.intern(KExpr::fvar(fv_id, name.clone())); self.lctx.push(fv_id, LocalDecl::CDecl { name, bi, ty }); @@ -852,7 +850,7 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { } pub fn debug_label_matches_env(&self) -> bool { - match std::env::var("IX_KERNEL_DEBUG_CONST") { + match crate::env_var("IX_KERNEL_DEBUG_CONST") { Ok(filter) if filter.is_empty() => true, Ok(filter) => { self.debug_label.as_ref().is_some_and(|label| label.contains(&filter)) @@ -865,10 +863,10 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { #[inline] pub fn tick(&mut self) -> Result<(), TcError> { if self.rec_fuel == 0 { - if std::env::var("IX_REC_FUEL_DUMP").is_ok() + if crate::env_var("IX_REC_FUEL_DUMP").is_ok() && self.debug_label_matches_env() { - eprintln!( + log::info!( "[rec fuel] exhausted const={} depth={} def_eq_depth={} infer_only={} native_reduce={} eager_reduce={}", self.debug_label.as_deref().unwrap_or(""), self.depth(), @@ -878,7 +876,7 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { self.eager_reduce ); self.dump_hot_misses(); - eprintln!("{}", std::backtrace::Backtrace::force_capture()); + log::info!("{}", std::backtrace::Backtrace::force_capture()); } return Err(TcError::MaxRecFuel); } @@ -928,6 +926,7 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { /// of `id`. No-op unless a `profile_sink` is installed. #[inline] pub(crate) fn record_delta_target(&mut self, id: &KId) { + crate::perf::record_delta_histo(&id.addr); if self.env.profile_sink.is_some() { self.delta_targets.insert(id.addr.clone()); } @@ -1013,9 +1012,9 @@ impl<'a, M: KernelMode> TypeChecker<'a, M> { } let mut entries: Vec<_> = self.hot_misses.iter().collect(); entries.sort_unstable_by(|a, b| b.1.cmp(a.1).then_with(|| a.0.cmp(b.0))); - eprintln!("[hot misses] top {}:", entries.len().min(25)); + log::info!("[hot misses] top {}:", entries.len().min(25)); for (key, count) in entries.into_iter().take(25) { - eprintln!(" {count:>8} {key}"); + log::info!(" {count:>8} {key}"); } } } @@ -1165,8 +1164,8 @@ mod tests { apps, cnst, mk_addr, mk_id, mk_name, pi, sort0, sort1, uzero, var, }; use super::*; - use crate::ix::address::Address; - use crate::ix::kernel::mode::Meta; + use crate::mode::Meta; + use ix_common::address::Address; fn new_tc() -> TypeChecker<'static, Meta> { let env = Box::leak(Box::new(KEnv::::new())); @@ -1682,7 +1681,7 @@ mod tests { // Deep embedding: λ x. app target (var 0) let e = KExpr::::lam( mk_name("x"), - crate::ix::env::BinderInfo::Default, + ix_common::env::BinderInfo::Default, sort0(), KExpr::app(target, var(0)), ); diff --git a/src/ix/kernel/testing.rs b/crates/kernel/src/testing.rs similarity index 97% rename from src/ix/kernel/testing.rs rename to crates/kernel/src/testing.rs index 2fa6e9c9..8c29a274 100644 --- a/src/ix/kernel/testing.rs +++ b/crates/kernel/src/testing.rs @@ -3,9 +3,9 @@ //! Provides convenience constructors for `KExpr`, `KUniv`, `KId`, //! and `KConst` to reduce boilerplate in hand-built test environments. -use crate::ix::address::Address; -use crate::ix::env::{BinderInfo, DefinitionSafety, Name, ReducibilityHints}; -use crate::ix::ixon::constant::DefKind; +use ix_common::address::Address; +use ix_common::env::{BinderInfo, DefinitionSafety, Name, ReducibilityHints}; +use ixon::constant::DefKind; use super::constant::KConst; use super::env::KEnv; diff --git a/src/ix/kernel/tutorial/basic.rs b/crates/kernel/src/tutorial/basic.rs similarity index 99% rename from src/ix/kernel/tutorial/basic.rs rename to crates/kernel/src/tutorial/basic.rs index e460fdd2..adbc562d 100644 --- a/src/ix/kernel/tutorial/basic.rs +++ b/crates/kernel/src/tutorial/basic.rs @@ -3,10 +3,10 @@ #[cfg(test)] mod tests { - use crate::ix::env::ReducibilityHints; - use crate::ix::kernel::env::KEnv; - use crate::ix::kernel::mode::Meta; - use crate::ix::kernel::testing::*; + use crate::env::KEnv; + use crate::mode::Meta; + use crate::testing::*; + use ix_common::env::ReducibilityHints; // ========================================================================== // Batch 1: Basic definitions (Tutorial.lean lines 16–60) diff --git a/src/ix/kernel/tutorial/defeq.rs b/crates/kernel/src/tutorial/defeq.rs similarity index 98% rename from src/ix/kernel/tutorial/defeq.rs rename to crates/kernel/src/tutorial/defeq.rs index 4c09634b..b97f9ee7 100644 --- a/src/ix/kernel/tutorial/defeq.rs +++ b/crates/kernel/src/tutorial/defeq.rs @@ -3,11 +3,11 @@ #[cfg(test)] mod tests { - use crate::ix::env::Name; - use crate::ix::kernel::constant::{KConst, RecRule}; - use crate::ix::kernel::env::KEnv; - use crate::ix::kernel::mode::Meta; - use crate::ix::kernel::testing::*; + use crate::constant::{KConst, RecRule}; + use crate::env::KEnv; + use crate::mode::Meta; + use crate::testing::*; + use ix_common::env::Name; // ========================================================================== // Batch 4: Proof irrelevance and eta (Tutorial.lean lines 953–1013) @@ -50,7 +50,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Abbrev, + ix_common::env::ReducibilityHints::Abbrev, ); env.insert(id.clone(), c); check_accepts(&mut env, &id); @@ -811,7 +811,7 @@ mod tests { // Value: fun α r a h p => Eq.refl p (BOGUS — claims reduction happened) let val = ME::lam( mk_name("α"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort1(), nlam( "r", @@ -1069,11 +1069,11 @@ mod tests { let minor_r = app(app(var(0), var(1)), eq_refl_r); let rule_rhs = ME::lam( mk_name("α"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort(param(1)), ME::lam( mk_name("a"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, var(0), nlam("motive", motive_ty_r, nlam("refl", minor_r, var(0))), ), @@ -1396,7 +1396,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Opaque, + ix_common::env::ReducibilityHints::Opaque, ); env.insert(id.clone(), c); check_rejects(&mut env, &id); @@ -1499,7 +1499,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Opaque, + ix_common::env::ReducibilityHints::Opaque, ); env.insert(id.clone(), c); check_rejects(&mut env, &id); @@ -1523,11 +1523,11 @@ mod tests { // fun {a} {b} (h : And a b) => .proj And 0 h let val = ME::lam( mk_name("a"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort0(), ME::lam( mk_name("b"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort0(), nlam("h", and_ab, ME::prj(mk_id("And"), 0, var(0))), ), @@ -1539,7 +1539,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Abbrev, + ix_common::env::ReducibilityHints::Abbrev, ); env.insert(id.clone(), c); check_accepts(&mut env, &id); @@ -1554,11 +1554,11 @@ mod tests { let val = ME::lam( mk_name("a"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort0(), ME::lam( mk_name("b"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort0(), nlam("h", and_ab, ME::prj(mk_id("And"), 1, var(0))), ), @@ -1570,7 +1570,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Abbrev, + ix_common::env::ReducibilityHints::Abbrev, ); env.insert(id.clone(), c); check_accepts(&mut env, &id); @@ -1903,7 +1903,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Opaque, + ix_common::env::ReducibilityHints::Opaque, ); env.insert(id.clone(), c); id @@ -2071,7 +2071,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Opaque, + ix_common::env::ReducibilityHints::Opaque, ); env.insert(id.clone(), c); check_rejects(&mut env, &id); @@ -2279,7 +2279,7 @@ mod tests { vec![], ty, val, - crate::ix::env::ReducibilityHints::Opaque, + ix_common::env::ReducibilityHints::Opaque, ); env.insert(id.clone(), c); check_rejects(&mut env, &id); diff --git a/src/ix/kernel/tutorial/inductive.rs b/crates/kernel/src/tutorial/inductive.rs similarity index 99% rename from src/ix/kernel/tutorial/inductive.rs rename to crates/kernel/src/tutorial/inductive.rs index 08df9731..67591714 100644 --- a/src/ix/kernel/tutorial/inductive.rs +++ b/crates/kernel/src/tutorial/inductive.rs @@ -3,11 +3,11 @@ #[cfg(test)] mod tests { - use crate::ix::env::{Name, ReducibilityHints}; - use crate::ix::kernel::constant::{KConst, RecRule}; - use crate::ix::kernel::env::KEnv; - use crate::ix::kernel::mode::Meta; - use crate::ix::kernel::testing::*; + use crate::constant::{KConst, RecRule}; + use crate::env::KEnv; + use crate::mode::Meta; + use crate::testing::*; + use ix_common::env::{Name, ReducibilityHints}; // ========================================================================== // Batch 3: Bad inductives (Tutorial.lean lines 247–610) diff --git a/src/ix/kernel/tutorial/mod.rs b/crates/kernel/src/tutorial/mod.rs similarity index 100% rename from src/ix/kernel/tutorial/mod.rs rename to crates/kernel/src/tutorial/mod.rs diff --git a/src/ix/kernel/tutorial/reduction.rs b/crates/kernel/src/tutorial/reduction.rs similarity index 98% rename from src/ix/kernel/tutorial/reduction.rs rename to crates/kernel/src/tutorial/reduction.rs index e57e4ae7..aa482201 100644 --- a/src/ix/kernel/tutorial/reduction.rs +++ b/crates/kernel/src/tutorial/reduction.rs @@ -3,12 +3,12 @@ #[cfg(test)] mod tests { - use crate::ix::env::{Name, ReducibilityHints}; - use crate::ix::kernel::constant::KConst; - use crate::ix::kernel::constant::RecRule; - use crate::ix::kernel::env::KEnv; - use crate::ix::kernel::mode::Meta; - use crate::ix::kernel::testing::*; + use crate::constant::KConst; + use crate::constant::RecRule; + use crate::env::KEnv; + use crate::mode::Meta; + use crate::testing::*; + use ix_common::env::{Name, ReducibilityHints}; // ========================================================================== // Batch 5: Peano arithmetic (Tutorial.lean lines 127–153) @@ -985,8 +985,8 @@ mod tests { // The zero kernel's infer_nat_type uses prims.nat to construct the type. // We use N as our Nat, so we need prims.nat = mk_id("N"). // aNatLit : N := NatVal(0) - use crate::ix::address::Address; - use lean_ffi::nat::Nat; + use bignat::Nat; + use ix_common::address::Address; let nat_0 = ME::nat(Nat::from(0u64), Address::hash(b"natval_0")); let (id, c) = mk_defn("aNatLit", 0, vec![], nat(), nat_0, ReducibilityHints::Opaque); @@ -1005,8 +1005,8 @@ mod tests { let mut env = nat_env(); let nat = || cnst("N", &[]); - use crate::ix::address::Address; - use lean_ffi::nat::Nat; + use bignat::Nat; + use ix_common::address::Address; let nat_3 = ME::nat(Nat::from(3u64), Address::hash(b"natval_3")); let succ_succ_succ_zero = app( @@ -1214,11 +1214,11 @@ mod tests { // mk_case fst snd = app(app(var(2), var(1)), var(0)) let rule_rhs = ME::lam( mk_name("α"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort(usucc(param(0))), ME::lam( mk_name("β"), - crate::ix::env::BinderInfo::Implicit, + ix_common::env::BinderInfo::Implicit, sort(usucc(param(1))), nlam( "motive", @@ -1468,7 +1468,7 @@ mod tests { let mut env = KEnv::::new(); add_eq_inductive(&mut env); - use crate::ix::env::QuotKind; + use ix_common::env::QuotKind; // Quot.{u} : {α : Sort u} → (α → α → Prop) → Sort u // depth 1 (inside α): α = var(0) @@ -1627,9 +1627,7 @@ mod tests { env } - fn quot_prims( - env: &KEnv, - ) -> crate::ix::kernel::primitive::Primitives { + fn quot_prims(env: &KEnv) -> crate::primitive::Primitives { let mut prims = test_prims(env); prims.quot_type = mk_id("Quot"); prims.quot_ctor = mk_id("Quot.mk"); diff --git a/src/ix/kernel/whnf.rs b/crates/kernel/src/whnf.rs similarity index 97% rename from src/ix/kernel/whnf.rs rename to crates/kernel/src/whnf.rs index 16d74f4d..78fa5df9 100644 --- a/src/ix/kernel/whnf.rs +++ b/crates/kernel/src/whnf.rs @@ -6,22 +6,22 @@ use std::sync::LazyLock; use rustc_hash::FxHashSet; -use crate::ix::address::Address; -use crate::ix::ixon::constant::DefKind; +use ix_common::address::Address; +use ixon::constant::DefKind; /// When set, emit a `[iota stuck]` line whenever `try_iota` can't resolve /// its major premise to a constructor. Set `IX_IOTA_STUCK=1` to activate /// and optionally pass a substring filter (e.g. `IX_IOTA_STUCK=Poly.rec`) /// to suppress recursor-unrelated noise. -static IX_IOTA_STUCK: LazyLock> = - LazyLock::new(|| std::env::var("IX_IOTA_STUCK").ok()); +static IX_IOTA_STUCK: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_IOTA_STUCK").ok()); /// When set, log total `nat_to_constructor` calls every 100k. Lets us see /// whether a given check is doing runaway Nat iota expansion (signalling /// a `Nat.rec motive base step N` whose step unconditionally forces `ih` /// \u2014 the pattern the old 2^20 threshold guarded against). -static IX_NAT_EXPAND_LOG: LazyLock = - LazyLock::new(|| std::env::var("IX_NAT_EXPAND_LOG").is_ok()); +static IX_NAT_EXPAND_LOG: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_NAT_EXPAND_LOG").is_ok()); /// Global counter for `nat_to_constructor` calls. Read lazily via /// `IX_NAT_EXPAND_LOG`. `fetch_add(_, Relaxed)` is a near-free no-op when @@ -29,34 +29,34 @@ static IX_NAT_EXPAND_LOG: LazyLock = static NAT_EXPAND_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); -static IX_NAT_IOTA_TRACE: LazyLock = - LazyLock::new(|| std::env::var("IX_NAT_IOTA_TRACE").is_ok()); +static IX_NAT_IOTA_TRACE: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_NAT_IOTA_TRACE").is_ok()); static NAT_IOTA_TRACE_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); -static IX_NAT_LINEAR_REC_TRACE: LazyLock = - LazyLock::new(|| std::env::var("IX_NAT_LINEAR_REC_TRACE").is_ok()); +static IX_NAT_LINEAR_REC_TRACE: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_NAT_LINEAR_REC_TRACE").is_ok()); static NAT_LINEAR_REC_TRACE_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); /// When set, log every 1M whnf entries. A check using tens of millions /// of whnf calls on a single constant is deep in pathological territory. -static IX_WHNF_COUNT_LOG: LazyLock = - LazyLock::new(|| std::env::var("IX_WHNF_COUNT_LOG").is_ok()); +static IX_WHNF_COUNT_LOG: crate::EnvFlag = + crate::EnvFlag::new(|| crate::env_var("IX_WHNF_COUNT_LOG").is_ok()); static WHNF_COUNT: std::sync::atomic::AtomicUsize = std::sync::atomic::AtomicUsize::new(0); -static IX_DELTA_TRACE: LazyLock> = - LazyLock::new(|| std::env::var("IX_DELTA_TRACE").ok()); +static IX_DELTA_TRACE: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_DELTA_TRACE").ok()); -static IX_PROJ_TRACE: LazyLock> = - LazyLock::new(|| std::env::var("IX_PROJ_TRACE").ok()); +static IX_PROJ_TRACE: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_PROJ_TRACE").ok()); -static IX_NAT_TRACE: LazyLock> = - LazyLock::new(|| std::env::var("IX_NAT_TRACE").ok()); +static IX_NAT_TRACE: crate::EnvString = + crate::EnvString::new(|| crate::env_var("IX_NAT_TRACE").ok()); const NAT_REDUCER_OPEN_ARG_REC_FUEL: u64 = 4096; @@ -69,7 +69,7 @@ use super::mode::KernelMode; use super::subst::{simul_subst, subst, subst_no_intern}; use super::tc::{IotaInfo, MAX_WHNF_FUEL, TypeChecker, collect_app_spine}; -use lean_ffi::nat::Nat; +use bignat::Nat; /// Reduction policy for structural WHNF. /// @@ -116,14 +116,14 @@ impl TypeChecker<'_, M> { original: &KExpr, current: &KExpr, ) { - if std::env::var("IX_WHNF_FUEL_DUMP").is_err() + if crate::env_var("IX_WHNF_FUEL_DUMP").is_err() || !self.debug_label_matches_env() { return; } let (orig_head, orig_args) = collect_app_spine(original); let (cur_head, cur_args) = collect_app_spine(current); - eprintln!( + log::info!( "[whnf fuel] {phase} const={} depth={} original_head={} original_args={} current_head={} current_args={}", self.debug_label.as_deref().unwrap_or(""), self.depth(), @@ -132,8 +132,8 @@ impl TypeChecker<'_, M> { cur_head, cur_args.len() ); - eprintln!(" original: {original}"); - eprintln!(" current: {current}"); + log::info!(" original: {original}"); + log::info!(" current: {current}"); } fn dump_delta_trace(&self, id: &KId, arity: usize, e: &KExpr) { @@ -147,7 +147,7 @@ impl TypeChecker<'_, M> { if !filter.is_empty() && !id_s.contains(filter) { return; } - eprintln!( + log::info!( "[delta] const={} depth={} head={} args={arity} expr={}", self.debug_label.as_deref().unwrap_or(""), self.depth(), @@ -176,7 +176,7 @@ impl TypeChecker<'_, M> { } let (head, args) = collect_app_spine(wval); match result { - Some(result) => eprintln!( + Some(result) => log::info!( "[proj] const={} depth={} proj={} field={} struct_head={} struct_args={} ctor_params={:?} result={}", self.debug_label.as_deref().unwrap_or(""), self.depth(), @@ -187,7 +187,7 @@ impl TypeChecker<'_, M> { ctor_params, result ), - None => eprintln!( + None => log::info!( "[proj] const={} depth={} proj={} field={} struct_head={} struct_args={} ctor_params={:?} result=", self.debug_label.as_deref().unwrap_or(""), self.depth(), @@ -212,7 +212,7 @@ impl TypeChecker<'_, M> { if !filter.is_empty() && !head_s.contains(filter) { return; } - eprintln!( + log::info!( "[nat] const={} depth={} phase={} head={} args={} expr={}", self.debug_label.as_deref().unwrap_or(""), self.depth(), @@ -236,7 +236,7 @@ impl TypeChecker<'_, M> { if *IX_WHNF_COUNT_LOG { let n = WHNF_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); if n.is_multiple_of(100_000) && n > 0 { - eprintln!("[whnf] count={n}"); + log::info!("[whnf] count={n}"); } } // Quick exit for non-reducing forms. @@ -323,7 +323,7 @@ impl TypeChecker<'_, M> { } // String literal primitives such as `String.back ""`. - if let Some(reduced) = self.try_reduce_string(&cur)? { + if let Some(reduced) = self.try_reduce_string(&cur) { cur = reduced; continue; } @@ -721,7 +721,7 @@ impl TypeChecker<'_, M> { } // String literal primitives. - if let Some(reduced) = self.try_reduce_string(&cur)? { + if let Some(reduced) = self.try_reduce_string(&cur) { cur = reduced; continue; } @@ -934,7 +934,7 @@ impl TypeChecker<'_, M> { let n = NAT_IOTA_TRACE_COUNT .fetch_add(1, std::sync::atomic::Ordering::Relaxed); if n < 32 { - eprintln!( + log::info!( "[nat_iota_trace] rec={} major_bits={} spine={} major_idx={}", rec_id, val.0.bits(), @@ -978,13 +978,14 @@ impl TypeChecker<'_, M> { if !is_ctor && let Some(filter) = IX_IOTA_STUCK.as_ref() { let rec_name = format!("{rec_id}"); if filter.is_empty() || rec_name.contains(filter) { - eprintln!("[iota stuck] rec={rec_name}"); - eprintln!("[iota stuck] major: {major}"); - eprintln!("[iota stuck] major whnf: {major_whnf}"); + log::info!("[iota stuck] rec={rec_name}"); + log::info!("[iota stuck] major: {major}"); + log::info!("[iota stuck] major whnf: {major_whnf}"); } } if is_ctor { + crate::perf::record_iota_histo(&rec_id.addr); let ctor_id = match ctor_head.data() { ExprData::Const(id, _, _) => id, _ => unreachable!(), @@ -1672,7 +1673,7 @@ impl TypeChecker<'_, M> { let n = NAT_EXPAND_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); if n.is_multiple_of(10_000) { - eprintln!("[nat_to_constructor] count={n} val_bits={}", val.0.bits()); + log::info!("[nat_to_constructor] count={n} val_bits={}", val.0.bits()); } } if val.0 == BigUint::ZERO { @@ -1792,6 +1793,18 @@ impl TypeChecker<'_, M> { &mut self, arg: &KExpr, ) -> Result>, TcError> { + // Stuck-chain memo. The inner WHNF below runs in `NatSuccMode::Stuck`, + // which bypasses the WHNF caches, so without this memo a stuck + // `succ^k(x)` chain is re-peeled in full from every depth it is + // encountered at — O(k²) fuel for `x + literal` on a symbolic `x`. + // Every suffix of a stuck chain is itself stuck, so on the stuck exit + // all visited keys are recorded. + let entry_key = self.whnf_key(arg); + if self.env.nat_succ_stuck.contains(&entry_key) { + return Ok(None); + } + let mut visited: Vec<(super::env::Addr, super::env::Addr)> = + vec![entry_key]; let mut offset = num_bigint::BigUint::from(1u64); let mut cur = arg.clone(); @@ -1814,11 +1827,24 @@ impl TypeChecker<'_, M> { && id.addr == self.prims.nat_succ.addr && args.len() == 1 { + crate::perf::record_nat_succ_peel(); offset += 1u64; cur = args[0].clone(); + let cur_key = self.whnf_key(&cur); + if self.env.nat_succ_stuck.contains(&cur_key) { + // Known-stuck suffix: the whole chain above it is stuck too. + self.env.nat_succ_stuck.extend(visited); + return Ok(None); + } + visited.push(cur_key); + // The whnf'd form `succ(cur)` can also surface later as a + // succ-iter argument; record it alongside the raw chain. + let w_key = self.whnf_key(&w); + visited.push(w_key); continue; } + self.env.nat_succ_stuck.extend(visited); return Ok(None); } } @@ -1842,7 +1868,7 @@ impl TypeChecker<'_, M> { .fetch_add(1, std::sync::atomic::Ordering::Relaxed); if n < 8 { let step_whnf = self.whnf(step)?; - eprintln!( + log::info!( "[nat_linear_rec] major_bits={} base_idx={} step_idx={} spine={} step_whnf={}", parts.major.0.bits(), parts.base_idx, @@ -2756,46 +2782,43 @@ impl TypeChecker<'_, M> { // String primitive reduction // ----------------------------------------------------------------------- - pub(super) fn try_reduce_string( - &mut self, - e: &KExpr, - ) -> Result>, TcError> { + pub(super) fn try_reduce_string(&mut self, e: &KExpr) -> Option> { let (head, args) = collect_app_spine(e); if args.len() != 1 { - return Ok(None); + return None; } let ExprData::Const(id, _, _) = head.data() else { - return Ok(None); + return None; }; let is_back = id.addr == self.prims.string_back.addr || id.addr == self.prims.string_legacy_back.addr; let is_utf8_byte_size = id.addr == self.prims.string_utf8_byte_size.addr; let is_to_byte_array = id.addr == self.prims.string_to_byte_array.addr; if !is_back && !is_utf8_byte_size && !is_to_byte_array { - return Ok(None); + return None; } let s = match args[0].data() { ExprData::Str(s, _, _) => s, - _ => return Ok(None), + _ => return None, }; if is_utf8_byte_size { let n = Nat::from(s.len() as u64); let addr = Address::hash(&n.to_le_bytes()); - return Ok(Some(self.intern(KExpr::nat(n, addr)))); + return Some(self.intern(KExpr::nat(n, addr))); } if is_to_byte_array { if s.is_empty() { - return Ok(Some(self.intern(KExpr::cnst( + return Some(self.intern(KExpr::cnst( self.prims.byte_array_empty.clone(), Box::new([]), - )))); + ))); } - return Ok(None); + return None; } let codepoint = s.chars().last().map_or(65u32, u32::from); - Ok(Some(self.char_of_nat_expr(u64::from(codepoint)))) + Some(self.char_of_nat_expr(u64::from(codepoint))) } fn char_of_nat_expr(&mut self, n: u64) -> KExpr { @@ -3027,9 +3050,9 @@ mod tests { use super::super::primitive::Primitives; use super::super::tc::TypeChecker; use super::*; - use crate::ix::address::Address; - use crate::ix::env::{DefinitionSafety, ReducibilityHints}; - use crate::ix::ixon::constant::DefKind; + use ix_common::address::Address; + use ix_common::env::{DefinitionSafety, ReducibilityHints}; + use ixon::constant::DefKind; type AE = KExpr; type AU = KUniv; @@ -4151,7 +4174,7 @@ mod tests { }, ExprData::App(..) => { // Might be Nat.succ chain — that's also acceptable - eprintln!("Nat.rec result is App chain (not folded to literal)"); + log::info!("Nat.rec result is App chain (not folded to literal)"); }, other => panic!("unexpected Nat.rec result: {:?}", other), } diff --git a/flake.lock b/flake.lock index 74d923ce..7468797d 100644 --- a/flake.lock +++ b/flake.lock @@ -76,6 +76,21 @@ "type": "github" } }, + "crane_3": { + "locked": { + "lastModified": 1774313767, + "narHash": "sha256-hy0XTQND6avzGEUFrJtYBBpFa/POiiaGBr2vpU6Y9tY=", + "owner": "ipetkov", + "repo": "crane", + "rev": "3d9df76e29656c679c744968b17fbaf28f0e923d", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, "fenix": { "inputs": { "nixpkgs": [ @@ -121,6 +136,28 @@ "type": "github" } }, + "fenix_3": { + "inputs": { + "nixpkgs": [ + "zisk", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src_3" + }, + "locked": { + "lastModified": 1774596377, + "narHash": "sha256-DiSLMxyTwIUAlhOe34r6kKNQRv6PTF+vf0MG45mAyn4=", + "owner": "nix-community", + "repo": "fenix", + "rev": "a88a1c8cf2f094da6347fcec54089f4bcb518409", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, "flake-parts": { "inputs": { "nixpkgs-lib": "nixpkgs-lib" @@ -175,6 +212,42 @@ "type": "github" } }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_4" + }, + "locked": { + "lastModified": 1772408722, + "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_5": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib_5" + }, + "locked": { + "lastModified": 1772408722, + "narHash": "sha256-rHuJtdcOjK7rAHpHphUb1iCvgkU3GpfvicLMwwnfMT0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "f20dc5d9b8027381c474144ecabc9034d6a839a3", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, "lean4-nix": { "inputs": { "flake-parts": "flake-parts_3", @@ -255,6 +328,52 @@ "type": "github" } }, + "nixpkgs-lib_4": { + "locked": { + "lastModified": 1772328832, + "narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs-lib_5": { + "locked": { + "lastModified": 1772328832, + "narHash": "sha256-e+/T/pmEkLP6BHhYjx6GmwP5ivonQQn0bJdH9YrRB+Q=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "c185c7a5e5dd8f9add5b2f8ebeff00888b070742", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1774386573, + "narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "blake3-lean": "blake3-lean", @@ -265,7 +384,9 @@ "nixpkgs": [ "lean4-nix", "nixpkgs" - ] + ], + "sp1": "sp1", + "zisk": "zisk" } }, "rust-analyzer-src": { @@ -301,6 +422,66 @@ "repo": "rust-analyzer", "type": "github" } + }, + "rust-analyzer-src_3": { + "flake": false, + "locked": { + "lastModified": 1774569884, + "narHash": "sha256-E8iWEPzg7OnE0XXXjo75CX7xFauqzJuGZ5wSO9KS8Ek=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "443ddcddd0c73b07b799d052f5ef3b448c2f3508", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "sp1": { + "inputs": { + "flake-parts": "flake-parts_4", + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1778884899, + "narHash": "sha256-kQahZHfD2f6tEaqD6WBDHDnjSr5m8x/IIS8VKu5glTw=", + "owner": "argumentcomputer", + "repo": "sp1.nix", + "rev": "048405ea52a9acb3fdd4eb7ad8c82346e93c4924", + "type": "github" + }, + "original": { + "owner": "argumentcomputer", + "repo": "sp1.nix", + "type": "github" + } + }, + "zisk": { + "inputs": { + "crane": "crane_3", + "fenix": "fenix_3", + "flake-parts": "flake-parts_5", + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1778885240, + "narHash": "sha256-hjbDg9V2q5fwoeBBjE/14a3YwQGwMImV/Apu0CMYSVY=", + "owner": "argumentcomputer", + "repo": "zisk.nix", + "rev": "d7fd3b8353dada23f9530716d1d8265b10c7808e", + "type": "github" + }, + "original": { + "owner": "argumentcomputer", + "ref": "fixups", + "repo": "zisk.nix", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index ad7c254b..3188ce4c 100644 --- a/flake.nix +++ b/flake.nix @@ -35,18 +35,30 @@ # System packages, follows lean4-nix so we stay in sync inputs.lean4-nix.follows = "lean4-nix"; }; + + # Zisk dev shell (cargo-zisk, ziskemu, RISC-V toolchain) for `zisk-guest`. + zisk.url = "github:argumentcomputer/zisk.nix/fixups"; + + # SP1 dev shell (cargo-prove + succinct Rust toolchain) for `sp1/guest`. + sp1 = { + url = "github:argumentcomputer/sp1.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; - outputs = inputs @ { - nixpkgs, - flake-parts, - lean4-nix, - fenix, - crane, - blake3-lean, - ... - }: - flake-parts.lib.mkFlake {inherit inputs;} { + outputs = + inputs@{ + nixpkgs, + flake-parts, + lean4-nix, + fenix, + crane, + blake3-lean, + zisk, + sp1, + ... + }: + flake-parts.lib.mkFlake { inherit inputs; } { # Systems we want to build for systems = [ "aarch64-darwin" @@ -55,149 +67,197 @@ "x86_64-linux" ]; - perSystem = { - system, - pkgs, - ... - }: let - # Pins the Rust toolchain - rustToolchain = fenix.packages.${system}.fromToolchainFile { - file = ./rust-toolchain.toml; - sha256 = "sha256-sqSWJDUxc+zaz1nBWMAJKTAGBuGWP25GCftIOlCEAtA="; - }; + perSystem = + { + system, + pkgs, + ... + }: + let + # Pins the Rust toolchain + rustToolchain = fenix.packages.${system}.fromToolchainFile { + file = ./rust-toolchain.toml; + sha256 = "sha256-sqSWJDUxc+zaz1nBWMAJKTAGBuGWP25GCftIOlCEAtA="; + }; + + # Rust package + craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; + src = craneLib.cleanCargoSource ./.; + craneArgs = { + inherit src; + pname = "ix"; + version = "0.1.0"; + strictDeps = true; - # Rust package - craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain; - src = craneLib.cleanCargoSource ./.; - craneArgs = { - inherit src; - strictDeps = true; - - # build.rs uses LEAN_SYSROOT to locate lean/lean.h for bindgen - LEAN_SYSROOT = "${pkgs.lean.lean-all}"; - # bindgen needs libclang to parse C headers - LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; - - buildInputs = - [] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ - # Additional darwin specific inputs can be set here - pkgs.libiconv + # build.rs uses LEAN_SYSROOT to locate lean/lean.h for bindgen + LEAN_SYSROOT = "${pkgs.lean.lean-all}"; + # bindgen needs libclang to parse C headers + LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; + + buildInputs = + [ ] + ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ + # Additional darwin specific inputs can be set here + pkgs.libiconv + ]; + }; + cargoArtifacts = craneLib.buildDepsOnly craneArgs; + + # Test build: parallel + test-ffi (only used by ixTest) + rustPkg = craneLib.buildPackage ( + craneArgs + // { + inherit cargoArtifacts; + cargoExtraArgs = "--locked --features parallel,test-ffi"; + } + ); + + # Release build without test-ffi (for distribution) + rustPkgRelease = craneLib.buildPackage ( + craneArgs + // { + inherit cargoArtifacts; + cargoExtraArgs = "--locked --features parallel"; + } + ); + + # Lake package + lake2nix = pkgs.callPackage lean4-nix.lake { }; + lakeDeps = lake2nix.buildDeps { + src = ./.; + depOverrideDeriv = { + Blake3 = blake3-lean.packages.${system}.rust; + }; + }; + # Shared Lake build args: patches out the Cargo build (Crane handles it) + mkLakeBuildArgs = rustLib: { + inherit lakeDeps; + src = ./.; + # Don't build the `ix_rs` static lib with Lake, since we build it with Crane + postPatch = '' + substituteInPlace lakefile.lean --replace-fail 'proc { cmd := "cargo"' '--proc { cmd := "cargo"' + ''; + # Symlink the Crane-built static lib to where Lake expects it + postConfigure = '' + mkdir -p target/release + ln -s ${rustLib}/lib/libix_ffi.a target/release/ + ''; + buildInputs = [ + pkgs.gmp + pkgs.lean.lean-all + pkgs.rsync ]; - }; - cargoArtifacts = craneLib.buildDepsOnly craneArgs; - - # Test build: parallel + test-ffi (only used by ixTest) - rustPkg = craneLib.buildPackage (craneArgs - // { - inherit cargoArtifacts; - cargoExtraArgs = "--locked --features parallel,test-ffi"; - }); - - # Release build without test-ffi (for distribution) - rustPkgRelease = craneLib.buildPackage (craneArgs - // { - inherit cargoArtifacts; - cargoExtraArgs = "--locked --features parallel"; - }); - - # Lake package - lake2nix = pkgs.callPackage lean4-nix.lake {}; - lakeDeps = lake2nix.buildDeps { - src = ./.; - depOverrideDeriv = { - Blake3 = blake3-lean.packages.${system}.rust; }; - }; - # Shared Lake build args: patches out the Cargo build (Crane handles it) - mkLakeBuildArgs = rustLib: { - inherit lakeDeps; - src = ./.; - # Don't build the `ix_rs` static lib with Lake, since we build it with Crane - postPatch = '' - substituteInPlace lakefile.lean --replace-fail 'proc { cmd := "cargo"' '--proc { cmd := "cargo"' - ''; - # Symlink the Crane-built static lib to where Lake expects it - postConfigure = '' - mkdir -p target/release - ln -s ${rustLib}/lib/libix_rs.a target/release/ - ''; - buildInputs = [pkgs.gmp pkgs.lean.lean-all pkgs.rsync]; - }; - # Release build args (no test-ffi symbols) - lakeBuildArgs = mkLakeBuildArgs rustPkgRelease; - # Test build args (includes test-ffi symbols) - lakeTestBuildArgs = mkLakeBuildArgs rustPkg; - - ixLib = lake2nix.mkPackage (lakeBuildArgs - // { - name = "Ix"; - buildLibrary = true; - }); - lakeBinArgs = - lakeBuildArgs - // { + # Release build args (no test-ffi symbols) + lakeBuildArgs = mkLakeBuildArgs rustPkgRelease; + # Test build args (includes test-ffi symbols) + lakeTestBuildArgs = mkLakeBuildArgs rustPkg; + + ixLib = lake2nix.mkPackage ( + lakeBuildArgs + // { + name = "Ix"; + buildLibrary = true; + } + ); + lakeBinArgs = lakeBuildArgs // { lakeArtifacts = ixLib; # Binaries that import Ix.Meta need .olean files at runtime via LEAN_PATH installArtifacts = true; }; - leanPath = pkgs.lib.concatStringsSep ":" ( - map (d: "${d}/.lake/build/lib/lean") ([ixLib] ++ builtins.attrValues lakeDeps) - ); - wrapBin = drv: - pkgs.runCommand drv.name {nativeBuildInputs = [pkgs.makeWrapper];} '' - mkdir -p $out/bin - for f in ${drv}/bin/*; do - [ -x "$f" ] || continue - makeWrapper "$f" "$out/bin/$(basename "$f")" \ - --set LEAN_SYSROOT "${pkgs.lean.lean-all}" \ - --set LEAN_PATH "${drv}/.lake/build/lib/lean:${leanPath}" - done - ''; - ixCLI = wrapBin (lake2nix.mkPackage (lakeBinArgs // {name = "ix";})); - # Test binary links rustPkg (with test-ffi) instead of rustPkgRelease - ixTest = wrapBin (lake2nix.mkPackage (lakeTestBuildArgs - // { - name = "IxTests"; - installArtifacts = true; - })); - ZKVotingProver = wrapBin (lake2nix.mkPackage (lakeBinArgs - // { - name = "Apps.ZKVoting.Prover"; - installArtifacts = true; - })); - in { - # Lean overlay - _module.args.pkgs = import nixpkgs { - inherit system; - overlays = [(lean4-nix.readToolchainFile ./lean-toolchain)]; - }; + leanPath = pkgs.lib.concatStringsSep ":" ( + map (d: "${d}/.lake/build/lib/lean") ([ ixLib ] ++ builtins.attrValues lakeDeps) + ); + wrapBin = + drv: + pkgs.runCommand drv.name { nativeBuildInputs = [ pkgs.makeWrapper ]; } '' + mkdir -p $out/bin + for f in ${drv}/bin/*; do + [ -x "$f" ] || continue + makeWrapper "$f" "$out/bin/$(basename "$f")" \ + --set LEAN_SYSROOT "${pkgs.lean.lean-all}" \ + --set LEAN_PATH "${drv}/.lake/build/lib/lean:${leanPath}" + done + ''; + ixCLI = wrapBin (lake2nix.mkPackage (lakeBinArgs // { name = "ix"; })); + # Test binary links rustPkg (with test-ffi) instead of rustPkgRelease + ixTest = wrapBin ( + lake2nix.mkPackage ( + lakeTestBuildArgs + // { + name = "IxTests"; + installArtifacts = true; + } + ) + ); + ZKVotingProver = wrapBin ( + lake2nix.mkPackage ( + lakeBinArgs + // { + name = "Apps.ZKVoting.Prover"; + installArtifacts = true; + } + ) + ); + in + { + # Lean overlay + _module.args.pkgs = import nixpkgs { + inherit system; + overlays = [ (lean4-nix.readToolchainFile ./lean-toolchain) ]; + }; - packages = { - default = ixLib; - ix = ixCLI; - test = ixTest; - zkv-prover = ZKVotingProver // {meta.mainProgram = "Apps-ZKVoting-Prover";}; - }; + packages = { + default = ixLib; + ix = ixCLI; + test = ixTest; + zkv-prover = ZKVotingProver // { + meta.mainProgram = "Apps-ZKVoting-Prover"; + }; + }; - # Provide a unified dev shell with Lean + Rust - devShells.default = pkgs.mkShell { - # Add libclang for FFI with rust-bindgen - LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; - packages = with pkgs; [ - pkg-config - openssl - clang - rustToolchain - rust-analyzer - lean.lean-all # Includes Lean compiler, lake, stdlib, etc. - cargo-deny - valgrind - ]; - }; + # Lean + Rust shell for host development (`cargo build`, `lake build`). + devShells.default = pkgs.mkShell { + LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; + packages = with pkgs; [ + pkg-config + openssl + clang + rustToolchain + rust-analyzer + lean.lean-all + cargo-deny + valgrind + ]; + }; - formatter = pkgs.alejandra; - }; + # Zisk shell for `zisk-guest/` (cargo-zisk, ziskemu, RISC-V toolchain). + # Kept separate from `default`: merging cross-pollinates NIX_CFLAGS_COMPILE + # between zisk.nix's and this flake's nixpkgs, which breaks bindgen on + # `lean.h`. + devShells.zisk = zisk.devShells.${system}.default; + + # SP1 shell for `sp1/host` + `sp1/guest`: host Rust toolchain plus + # cargo-prove and the succinct Rust toolchain (~/.sp1) from sp1.nix. + # `rustup-shim` wraps the host `rustc` to dispatch to the succinct + # toolchain when `RUSTUP_TOOLCHAIN=succinct` (set by `sp1-build`); the + # plain host rustc doesn't know `riscv64im-succinct-zkvm-elf`. + # `sp1-prover-types`'s build script needs `protoc`. + devShells.sp1 = pkgs.mkShell { + name = "sp1"; + inputsFrom = [ sp1.devShells.${system}.default ]; + LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib"; + packages = with pkgs; [ + pkg-config + openssl + protobuf + clang + (sp1.packages.${system}.rustup-shim.override { inherit rustToolchain; }) + ]; + }; + + formatter = pkgs.alejandra; + }; }; } diff --git a/lake-manifest.json b/lake-manifest.json index 05e505ee..2c6d163c 100644 --- a/lake-manifest.json +++ b/lake-manifest.json @@ -25,10 +25,10 @@ "type": "git", "subDir": null, "scope": "", - "rev": "aaf530784082a2c00b0a93648741429d274102ca", + "rev": "d15f36cf76eb5834b0e623e02b97fd4d95e56cc7", "name": "Blake3", "manifestFile": "lake-manifest.json", - "inputRev": "aaf530784082a2c00b0a93648741429d274102ca", + "inputRev": "d15f36cf76eb5834b0e623e02b97fd4d95e56cc7", "inherited": false, "configFile": "lakefile.lean"}, {"url": "https://github.com/argumentcomputer/LSpec", diff --git a/lakefile.lean b/lakefile.lean index 5362daa8..8e2305f7 100644 --- a/lakefile.lean +++ b/lakefile.lean @@ -8,7 +8,7 @@ require LSpec from git "https://github.com/argumentcomputer/LSpec" @ "d3c15b93a1dd4e7c8d5c0c3825c9555737e55c3e" require Blake3 from git - "https://github.com/argumentcomputer/Blake3.lean" @ "aaf530784082a2c00b0a93648741429d274102ca" + "https://github.com/argumentcomputer/Blake3.lean" @ "d15f36cf76eb5834b0e623e02b97fd4d95e56cc7" require Cli from git "https://github.com/leanprover/lean4-cli" @ "v4.29.0" @@ -40,7 +40,7 @@ def cargoArgs (testFfi : Bool := false) (net : Bool := false) : IO (Array String if ixNoPar != some "1" then features := features.push "parallel" if net && !System.Platform.isOSX then features := features.push "net" if testFfi then features := features.push "test-ffi" - let buildArgs := #["build", "--release"] + let buildArgs := #["build", "--release", "-p", "ix-ffi"] if features.isEmpty then return buildArgs else return buildArgs ++ #["--features", ",".intercalate features.toList] @@ -48,7 +48,7 @@ def cargoArgs (testFfi : Bool := false) (net : Bool := false) : IO (Array String target ix_rs pkg : FilePath := do let args ← cargoArgs proc { cmd := "cargo", args, cwd := pkg.dir } (quiet := true) - inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_rs" + inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_ffi" /-- Rebuild the Rust static lib with `test-ffi`. Only triggered by `lake test` (via `moreLinkObjs` on `IxTests`). @@ -57,7 +57,7 @@ target ix_rs_test pkg : FilePath := do let _ ← ix_rs.fetch let args ← cargoArgs (testFfi := true) proc { cmd := "cargo", args, cwd := pkg.dir } (quiet := true) - inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_rs" + inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_ffi" /-- Build the Rust static lib with `net` for the `ix` CLI. Fetches `ix_rs` first to guarantee ordering before overwriting the lib. -/ @@ -65,7 +65,7 @@ target ix_rs_net pkg : FilePath := do let _ ← ix_rs.fetch let args ← cargoArgs (net := true) proc { cmd := "cargo", args, cwd := pkg.dir } (quiet := true) - inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_rs" + inputBinFile $ pkg.dir / "target" / "release" / nameToStaticLib "ix_ffi" end FFI @@ -122,6 +122,9 @@ lean_exe «bench-check-nat-add-comm» where root := `Benchmarks.CheckNatAddComm supportInterpreter := true +lean_exe «bench-compile-init» where + root := `Benchmarks.CompileInit + end Benchmarks section IxApplications diff --git a/sp1/.cargo/config.toml b/sp1/.cargo/config.toml new file mode 100644 index 00000000..9818452d --- /dev/null +++ b/sp1/.cargo/config.toml @@ -0,0 +1,9 @@ +[build] +rustflags = ["-C", "target-cpu=native"] + +# Wraps every binary with scripts/cuda-runner.sh, which cleans orphaned +# sp1-gpu-server sockets and retries on the SP1 SDK's CUDA-init race. +# Pass-through (no overhead, no retries) when SP1_PROVER != "cuda". +# Path is relative to cwd; this expects cargo to be invoked from sp1/. +[target.x86_64-unknown-linux-gnu] +runner = "./scripts/cuda-runner.sh" diff --git a/sp1/Cargo.lock b/sp1/Cargo.lock new file mode 100644 index 00000000..a5f9903d --- /dev/null +++ b/sp1/Cargo.lock @@ -0,0 +1,5920 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addchain" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" +dependencies = [ + "num-bigint 0.3.3", + "num-integer", + "num-traits", +] + +[[package]] +name = "addr2line" +version = "0.25.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-scoped" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4042078ea593edffc452eef14e99fdb2b120caa4ad9618bcdeabc4a023b98740" +dependencies = [ + "futures", + "pin-project", + "tokio", +] + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "async-trait" +version = "0.1.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "atomic" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "axum" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower 0.5.3", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "serde", + "windows-link", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "bignat" +version = "0.1.0" +source = "git+https://github.com/argumentcomputer/lean-ffi.git?rev=839b405de708b80504fda39abe1402114b4135a5#839b405de708b80504fda39abe1402114b4135a5" +dependencies = [ + "num-bigint 0.4.6", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake3" +version = "1.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array 0.14.9", +] + +[[package]] +name = "bumpalo" +version = "3.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "byte-slice-cast" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7575182f7272186991736b70173b0ea045398f984bf5ebbb3804736ce1330c9d" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "camino" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629a66d692cb9ff1a1c664e41771b3dcaf961985a9774c0eb0bd1b51cf60a48" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror 1.0.69", +] + +[[package]] +name = "cc" +version = "1.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +dependencies = [ + "iana-time-zone", + "num-traits", + "windows-link", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_format" +version = "0.2.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "crash-context" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "031ed29858d90cfdf27fe49fae28028a1f20466db97962fa2f4ea34809aeebf3" +dependencies = [ + "cfg-if", + "libc", + "mach2", +] + +[[package]] +name = "crash-handler" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0df5c9639f4942eb7702b964b3f9adf03a55724a57558cc177407388a8b936e2" +dependencies = [ + "cfg-if", + "crash-context", + "libc", + "mach2", + "parking_lot", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array 0.14.9", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array 0.14.9", + "typenum", +] + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", + "rayon", +] + +[[package]] +name = "dashu" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b3e5ac1e23ff1995ef05b912e2b012a8784506987a2651552db2c73fb3d7e0" +dependencies = [ + "dashu-base", + "dashu-float", + "dashu-int", + "dashu-macros", + "dashu-ratio", + "rustversion", +] + +[[package]] +name = "dashu-base" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b80bf6b85aa68c58ffea2ddb040109943049ce3fbdf4385d0380aef08ef289" + +[[package]] +name = "dashu-float" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85078445a8dbd2e1bd21f04a816f352db8d333643f0c9b78ca7c3d1df71063e7" +dependencies = [ + "dashu-base", + "dashu-int", + "num-modular", + "num-order", + "rustversion", + "static_assertions", +] + +[[package]] +name = "dashu-int" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee99d08031ca34a4d044efbbb21dff9b8c54bb9d8c82a189187c0651ffdb9fbf" +dependencies = [ + "cfg-if", + "dashu-base", + "num-modular", + "num-order", + "rustversion", + "static_assertions", +] + +[[package]] +name = "dashu-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93381c3ef6366766f6e9ed9cf09e4ef9dec69499baf04f0c60e70d653cf0ab10" +dependencies = [ + "dashu-base", + "dashu-float", + "dashu-int", + "dashu-ratio", + "paste", + "proc-macro2", + "quote", + "rustversion", +] + +[[package]] +name = "dashu-ratio" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e33b04dd7ce1ccf8a02a69d3419e354f2bbfdf4eb911a0b7465487248764c9" +dependencies = [ + "dashu-base", + "dashu-float", + "dashu-int", + "num-modular", + "num-order", + "rustversion", +] + +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + +[[package]] +name = "deepsize2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b5184084af9beed35eecbf4c36baf6e26b9dc47b61b74e02f930c72a58e71b" +dependencies = [ + "deepsize_derive2", + "hashbrown 0.14.5", +] + +[[package]] +name = "deepsize_derive2" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f8817865cacf3b93b943ca06b0fc5fd8e99eabfdb7ea5d296efcbc4afc4f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive-where" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dynasm" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7d4c414c94bc830797115b8e5f434d58e7e80cb42ba88508c14bc6ea270625" +dependencies = [ + "bitflags", + "byteorder", + "lazy_static", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dynasmrt" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "602f7458a3859195fb840e6e0cce5f4330dd9dfbfece0edaf31fe427af346f55" +dependencies = [ + "byteorder", + "dynasm", + "fnv", + "memmap2", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "serdect", + "signature", + "spki", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +dependencies = [ + "serde", +] + +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array 0.14.9", + "group", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "enum-map" +version = "2.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9" +dependencies = [ + "enum-map-derive", + "serde", +] + +[[package]] +name = "enum-map-derive" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "eventsource-stream" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" +dependencies = [ + "futures-core", + "nom", + "pin-project-lite", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "fastrand" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "bitvec", + "byteorder", + "ff_derive", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f10d12652036b0e99197587c6ba87a8fc3031986499973c030d8b44fcc151b60" +dependencies = [ + "addchain", + "num-bigint 0.3.3", + "num-integer", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "gecko_profile" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "890852c7e1e02bc6758e325d6b1e0236e4fbf21b492f585ce4d4715be54b4c6a" +dependencies = [ + "debugid", + "serde", + "serde_json", +] + +[[package]] +name = "gen_ops" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "304de19db7028420975a296ab0fcbbc8e69438c4ed254a1e41e2a7f37d5f0e0a" + +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "generic-array" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96512db27971c2c3eece70a1e106fbe6c87760234e31e8f7e5634912fe52794a" +dependencies = [ + "serde", + "typenum", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "gimli" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "h2" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.14.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "human-repr" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f58b778a5761513caf593693f8951c97a5b610841e754788400f32102eefdff1" + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2 0.6.3", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", + "serde", + "serde_core", +] + +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "ix-common" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "indexmap 2.14.0", + "rustc-hash", +] + +[[package]] +name = "ix-kernel" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "dashmap", + "indexmap 2.14.0", + "itertools 0.14.0", + "ix-common", + "ixon", + "log", + "num-bigint 0.4.6", + "rayon", + "rustc-hash", +] + +[[package]] +name = "ixon" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "dashmap", + "indexmap 2.14.0", + "ix-common", + "memmap2", + "num-bigint 0.4.6", + "rayon", + "rustc-hash", + "sha2", + "tiny-keccak", +] + +[[package]] +name = "js-sys" +version = "0.3.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "serdect", + "sha2", + "signature", +] + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libredox" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +dependencies = [ + "libc", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" + +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.5", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "mach2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix", +] + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "mti" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9563a7d5556636e74bbd8773241fbcbc5c89b9f6bfdc97b29b56e740c2c74b9" +dependencies = [ + "typeid_prefix", + "typeid_suffix", +] + +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint 0.4.6", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-modular" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f" + +[[package]] +name = "num-order" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6" +dependencies = [ + "num-modular", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint 0.4.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.37.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" +dependencies = [ + "crc32fast", + "flate2", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "memchr", + "ruzstd", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "opentelemetry" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b69a91d4893e713e06f724597ad630f1fa76057a5e1026c0ca67054a9032a76" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror 1.0.69", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p3-air" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a5de20a2301bf2530de1ceb13768ec3a80f729fbf8b72f813e30bc54c5bce2" +dependencies = [ + "p3-field", + "p3-matrix", + "serde", +] + +[[package]] +name = "p3-baby-bear" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69e6e9af4eaaaa60f7bb9f0e0f73ebcbaefe7e00974d97ad0fa542d6a4f0890" +dependencies = [ + "cfg-if", + "num-bigint 0.4.6", + "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", + "rand 0.8.6", + "rustc_version", + "serde", +] + +[[package]] +name = "p3-bn254-fr" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2077757c7cb514202ccb5368f521f23f5709c720599e6545c683c66e0a52d2d8" +dependencies = [ + "ff", + "num-bigint 0.4.6", + "p3-field", + "p3-poseidon2", + "p3-symmetric", + "rand 0.8.6", + "serde", +] + +[[package]] +name = "p3-challenger" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a908924d43e4cfb93fb41c8346cac211b70314385a9037e9241f5b7f3eaf77" +dependencies = [ + "p3-field", + "p3-maybe-rayon", + "p3-symmetric", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-commit" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50acacc7219fce6c01db938f82c1b21b5e7133990b7fff861f91534aeb569419" +dependencies = [ + "itertools 0.12.1", + "p3-challenger", + "p3-field", + "p3-matrix", + "p3-util", + "serde", +] + +[[package]] +name = "p3-dft" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be6408b10a2c27eb13a7d5580c546c2179a8dc7dbc10a990657311891f9b41c0" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-field" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dc75969ca3ac847f43e632ab979d59ff7a68f9eac8dbf8edcbba47fc2e1d3aa" +dependencies = [ + "itertools 0.12.1", + "num-bigint 0.4.6", + "num-traits", + "p3-util", + "rand 0.8.6", + "serde", +] + +[[package]] +name = "p3-fri" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cbc4965ee488f3247867b7ec4bb005b8afa72cb0d461a4dcb1387ecab6426d5" +dependencies = [ + "itertools 0.12.1", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-interpolation", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-interpolation" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ad7e9f08c336d7ea39d12e11951188473542565323bac2a6535e536b58487d" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-util", +] + +[[package]] +name = "p3-keccak-air" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f5bf177d56740078b5a5a842fa2393427796283dc8174b4a1a325c2d0b042de" +dependencies = [ + "p3-air", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-koala-bear" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9683cd0ef68100df7c62490533047bcf19c04c4a0fa1efc9d7c1e03e31f6b3" +dependencies = [ + "cfg-if", + "num-bigint 0.4.6", + "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", + "rand 0.8.6", + "rustc_version", + "serde", +] + +[[package]] +name = "p3-matrix" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c3f150ceb90e09539413bf481e618d05ee19210b4e467d2902eb82d2e15281" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "p3-maybe-rayon", + "p3-util", + "rand 0.8.6", + "serde", + "tracing", +] + +[[package]] +name = "p3-maybe-rayon" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0641952b42da45e1dfa2d4a2a3163e330f944ad9740942f35026c0a71a605f1" +dependencies = [ + "rayon", +] + +[[package]] +name = "p3-mds" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4a5f250e174dcfca5cbeac6ad75713924e7e7320e0a335e3c50b8b1f4fe8ec" +dependencies = [ + "itertools 0.12.1", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-symmetric", + "p3-util", + "rand 0.8.6", +] + +[[package]] +name = "p3-merkle-tree" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5703d9229d52a8c09970e4d722c3a8b4d37e688c306c3a1c03b872efcd204e6" +dependencies = [ + "itertools 0.12.1", + "p3-commit", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-symmetric", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-poseidon2" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "522986377b2164c5f94f2dae88e0e0a3d169cc6239202ef4aeb4322d60feffd0" +dependencies = [ + "gcd", + "p3-field", + "p3-mds", + "p3-symmetric", + "rand 0.8.6", + "serde", +] + +[[package]] +name = "p3-symmetric" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9047ce85c086a9b3f118e10078f10636f7bfeed5da871a04da0b61400af8793a" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "serde", +] + +[[package]] +name = "p3-uni-stark" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc3dfdeba14d8db621c4e52dd63973384ff35f353fd750154ff88397f4ea5adf" +dependencies = [ + "itertools 0.12.1", + "p3-air", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-util" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff962f8eaa5f36e0447cee7c241f6b4b475fadf3ee61f154327a26bb4e009ba" +dependencies = [ + "serde", +] + +[[package]] +name = "parity-scale-codec" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799781ae679d79a948e13d4824a40970bfa500058d245760dd857301059810fa" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "const_format", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "rustversion", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34b4653168b563151153c9e4c08ebed57fb8262bebfa79711552fa983c623e7a" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "petgraph" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" +dependencies = [ + "fixedbitset", + "indexmap 2.14.0", +] + +[[package]] +name = "pin-project" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit 0.25.11+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" +dependencies = [ + "heck", + "itertools 0.14.0", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.117", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "prost-types" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" +dependencies = [ + "prost", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2 0.6.3", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2 0.6.3", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "range-set-blaze" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8421b5d459262eabbe49048d362897ff3e3830b44eac6cfe341d6acb2f0f13d2" +dependencies = [ + "gen_ops", + "itertools 0.12.1", + "num-integer", + "num-traits", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "rayon-scan" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f87cc11a0140b4b0da0ffc889885760c61b13672d80a908920b2c0df078fa14" +dependencies = [ + "rayon", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 1.0.69", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower 0.5.3", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rrs-succinct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efd079cd303257a4cb4e5aadfa79a7fe23f3c8301aa4740ccc3a99673485a352" +dependencies = [ + "downcast-rs", + "num_enum", + "paste", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc-hex" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ruzstd" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c1c839d570d835527c9a5e4db7cb2198683a988cb9d7293fc8674e6bd58fc8" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "scale-info" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" +dependencies = [ + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array 0.14.9", + "pkcs8", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_arrays" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94a16b99c5ea4fe3daccd14853ad260ec00ea043b2708d1fd1da3106dcd8d9df" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "serial_test" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" +dependencies = [ + "futures-executor", + "futures-util", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slop-air" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-air", +] + +[[package]] +name = "slop-algebra" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "itertools 0.14.0", + "p3-field", + "serde", +] + +[[package]] +name = "slop-alloc" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "serde", + "slop-algebra", + "thiserror 1.0.69", +] + +[[package]] +name = "slop-baby-bear" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "lazy_static", + "p3-baby-bear", + "serde", + "slop-algebra", + "slop-challenger", + "slop-poseidon2", + "slop-symmetric", +] + +[[package]] +name = "slop-basefold" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "derive-where", + "itertools 0.14.0", + "serde", + "slop-algebra", + "slop-alloc", + "slop-baby-bear", + "slop-bn254", + "slop-challenger", + "slop-koala-bear", + "slop-merkle-tree", + "slop-multilinear", + "slop-primitives", + "slop-tensor", + "slop-utils", + "thiserror 1.0.69", +] + +[[package]] +name = "slop-basefold-prover" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "derive-where", + "itertools 0.14.0", + "rand 0.8.6", + "serde", + "slop-algebra", + "slop-alloc", + "slop-baby-bear", + "slop-basefold", + "slop-bn254", + "slop-challenger", + "slop-commit", + "slop-dft", + "slop-fri", + "slop-futures", + "slop-koala-bear", + "slop-merkle-tree", + "slop-multilinear", + "slop-tensor", + "thiserror 1.0.69", +] + +[[package]] +name = "slop-bn254" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "ff", + "p3-bn254-fr", + "serde", + "slop-algebra", + "slop-challenger", + "slop-poseidon2", + "slop-symmetric", +] + +[[package]] +name = "slop-challenger" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "futures", + "p3-challenger", + "serde", + "slop-algebra", + "slop-symmetric", +] + +[[package]] +name = "slop-commit" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-commit", + "serde", + "slop-alloc", +] + +[[package]] +name = "slop-dft" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-dft", + "serde", + "slop-algebra", + "slop-alloc", + "slop-matrix", + "slop-tensor", +] + +[[package]] +name = "slop-fri" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-fri", +] + +[[package]] +name = "slop-futures" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "crossbeam", + "futures", + "pin-project", + "rayon", + "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "slop-jagged" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "derive-where", + "futures", + "itertools 0.14.0", + "num_cpus", + "rand 0.8.6", + "rayon", + "serde", + "slop-algebra", + "slop-alloc", + "slop-baby-bear", + "slop-basefold", + "slop-basefold-prover", + "slop-bn254", + "slop-challenger", + "slop-commit", + "slop-futures", + "slop-koala-bear", + "slop-merkle-tree", + "slop-multilinear", + "slop-stacked", + "slop-sumcheck", + "slop-symmetric", + "slop-tensor", + "slop-utils", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "slop-keccak-air" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-keccak-air", +] + +[[package]] +name = "slop-koala-bear" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "lazy_static", + "p3-koala-bear", + "serde", + "slop-algebra", + "slop-challenger", + "slop-poseidon2", + "slop-symmetric", +] + +[[package]] +name = "slop-matrix" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-matrix", +] + +[[package]] +name = "slop-maybe-rayon" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-maybe-rayon", +] + +[[package]] +name = "slop-merkle-tree" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "derive-where", + "itertools 0.14.0", + "p3-merkle-tree", + "serde", + "slop-algebra", + "slop-alloc", + "slop-baby-bear", + "slop-bn254", + "slop-challenger", + "slop-commit", + "slop-futures", + "slop-koala-bear", + "slop-matrix", + "slop-poseidon2", + "slop-symmetric", + "slop-tensor", + "slop-utils", + "thiserror 1.0.69", +] + +[[package]] +name = "slop-multilinear" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "derive-where", + "futures", + "num_cpus", + "rand 0.8.6", + "rayon", + "serde", + "slop-algebra", + "slop-alloc", + "slop-challenger", + "slop-commit", + "slop-futures", + "slop-matrix", + "slop-tensor", +] + +[[package]] +name = "slop-poseidon2" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-poseidon2", +] + +[[package]] +name = "slop-primitives" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "slop-algebra", +] + +[[package]] +name = "slop-stacked" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "derive-where", + "futures", + "itertools 0.14.0", + "serde", + "slop-algebra", + "slop-alloc", + "slop-basefold", + "slop-basefold-prover", + "slop-challenger", + "slop-commit", + "slop-futures", + "slop-merkle-tree", + "slop-multilinear", + "slop-tensor", + "thiserror 1.0.69", +] + +[[package]] +name = "slop-sumcheck" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "futures", + "itertools 0.14.0", + "rayon", + "serde", + "slop-algebra", + "slop-alloc", + "slop-baby-bear", + "slop-challenger", + "slop-multilinear", + "thiserror 1.0.69", +] + +[[package]] +name = "slop-symmetric" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-symmetric", +] + +[[package]] +name = "slop-tensor" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "arrayvec", + "derive-where", + "itertools 0.14.0", + "rand 0.8.6", + "rayon", + "serde", + "slop-algebra", + "slop-alloc", + "slop-futures", + "slop-matrix", + "thiserror 1.0.69", + "transpose", +] + +[[package]] +name = "slop-uni-stark" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-uni-stark", +] + +[[package]] +name = "slop-utils" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-util", + "tracing-forest", + "tracing-subscriber", +] + +[[package]] +name = "slop-whir" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "derive-where", + "futures", + "itertools 0.14.0", + "rand 0.8.6", + "rayon", + "serde", + "slop-algebra", + "slop-alloc", + "slop-baby-bear", + "slop-basefold", + "slop-challenger", + "slop-commit", + "slop-dft", + "slop-jagged", + "slop-koala-bear", + "slop-matrix", + "slop-merkle-tree", + "slop-multilinear", + "slop-stacked", + "slop-tensor", + "slop-utils", + "thiserror 1.0.69", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "sp1-build" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "anyhow", + "cargo_metadata", + "chrono", + "clap", + "dirs", + "sp1-primitives", +] + +[[package]] +name = "sp1-core-executor" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "bytemuck", + "cfg-if", + "clap", + "deepsize2", + "elf", + "enum-map", + "eyre", + "gecko_profile", + "hashbrown 0.14.5", + "hex", + "indicatif", + "itertools 0.14.0", + "memmap2", + "num", + "object", + "rrs-succinct", + "rustc-demangle", + "serde", + "serde_arrays", + "serde_json", + "slop-air", + "slop-algebra", + "slop-maybe-rayon", + "slop-symmetric", + "sp1-curves", + "sp1-hypercube", + "sp1-jit", + "sp1-primitives", + "strum", + "subenum", + "thiserror 1.0.69", + "tiny-keccak", + "tracing", + "typenum", + "vec_map", +] + +[[package]] +name = "sp1-core-executor-runner" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "base64", + "bincode", + "cargo_metadata", + "hashbrown 0.14.5", + "hex", + "libc", + "sha2", + "sp1-core-executor", + "sp1-core-executor-runner-binary", + "sp1-jit", + "sp1-primitives", + "sysinfo", + "tracing", + "uuid", +] + +[[package]] +name = "sp1-core-executor-runner-binary" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "crash-handler", + "libc", + "serde", + "sp1-core-executor", + "sp1-jit", + "tracing-subscriber", +] + +[[package]] +name = "sp1-core-machine" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "cfg-if", + "enum-map", + "futures", + "generic-array 1.1.0", + "hashbrown 0.14.5", + "itertools 0.14.0", + "num", + "num_cpus", + "rayon", + "rayon-scan", + "rrs-succinct", + "serde", + "serde_json", + "slop-air", + "slop-algebra", + "slop-challenger", + "slop-futures", + "slop-keccak-air", + "slop-matrix", + "slop-maybe-rayon", + "slop-uni-stark", + "snowbridge-amcl", + "sp1-core-executor", + "sp1-core-executor-runner", + "sp1-curves", + "sp1-derive", + "sp1-hypercube", + "sp1-jit", + "sp1-primitives", + "static_assertions", + "struct-reflection", + "strum", + "sysinfo", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tracing", + "tracing-forest", + "tracing-subscriber", + "typenum", +] + +[[package]] +name = "sp1-cuda" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "bytes", + "reqwest", + "serde", + "serde_json", + "sp1-core-executor", + "sp1-core-machine", + "sp1-hypercube", + "sp1-primitives", + "sp1-prover", + "sp1-prover-types", + "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "sp1-curves" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "cfg-if", + "dashu", + "elliptic-curve", + "generic-array 1.1.0", + "itertools 0.14.0", + "k256", + "num", + "p256", + "serde", + "slop-algebra", + "snowbridge-amcl", + "sp1-primitives", + "typenum", +] + +[[package]] +name = "sp1-derive" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp1-host" +version = "0.1.0" +dependencies = [ + "anyhow", + "bincode", + "clap", + "human-repr", + "ix-common", + "ix-kernel", + "ixon", + "sp1-build", + "sp1-sdk", + "tokio", +] + +[[package]] +name = "sp1-hypercube" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "arrayref", + "deepsize2", + "derive-where", + "futures", + "hashbrown 0.14.5", + "itertools 0.14.0", + "num-bigint 0.4.6", + "num-traits", + "num_cpus", + "rayon", + "rayon-scan", + "serde", + "slop-air", + "slop-algebra", + "slop-alloc", + "slop-basefold", + "slop-basefold-prover", + "slop-bn254", + "slop-challenger", + "slop-commit", + "slop-futures", + "slop-jagged", + "slop-koala-bear", + "slop-matrix", + "slop-merkle-tree", + "slop-multilinear", + "slop-poseidon2", + "slop-stacked", + "slop-sumcheck", + "slop-symmetric", + "slop-tensor", + "slop-uni-stark", + "slop-whir", + "sp1-derive", + "sp1-primitives", + "struct-reflection", + "strum", + "thiserror 1.0.69", + "thousands", + "tokio", + "tracing", +] + +[[package]] +name = "sp1-jit" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "dynasmrt", + "hashbrown 0.14.5", + "libc", + "memfd", + "memmap2", + "serde", + "sp1-primitives", + "tracing", + "uuid", +] + +[[package]] +name = "sp1-primitives" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "blake3", + "elf", + "hex", + "itertools 0.14.0", + "lazy_static", + "num-bigint 0.4.6", + "serde", + "sha2", + "slop-algebra", + "slop-bn254", + "slop-challenger", + "slop-koala-bear", + "slop-poseidon2", + "slop-primitives", + "slop-symmetric", +] + +[[package]] +name = "sp1-prover" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "anyhow", + "bincode", + "clap", + "dirs", + "either", + "enum-map", + "eyre", + "futures", + "hashbrown 0.14.5", + "hex", + "indicatif", + "itertools 0.14.0", + "lru", + "mti", + "num-bigint 0.4.6", + "opentelemetry", + "pin-project", + "rand 0.8.6", + "reqwest", + "serde", + "serde_json", + "serial_test", + "sha2", + "slop-air", + "slop-algebra", + "slop-basefold", + "slop-bn254", + "slop-challenger", + "slop-futures", + "slop-jagged", + "slop-multilinear", + "slop-stacked", + "slop-symmetric", + "sp1-core-executor", + "sp1-core-executor-runner", + "sp1-core-machine", + "sp1-derive", + "sp1-hypercube", + "sp1-jit", + "sp1-primitives", + "sp1-prover-types", + "sp1-recursion-circuit", + "sp1-recursion-compiler", + "sp1-recursion-executor", + "sp1-recursion-gnark-ffi", + "sp1-recursion-machine", + "sp1-verifier", + "static_assertions", + "sysinfo", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tonic", + "tracing", + "tracing-appender", + "tracing-subscriber", +] + +[[package]] +name = "sp1-prover-types" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "anyhow", + "async-scoped", + "bincode", + "chrono", + "futures-util", + "hashbrown 0.14.5", + "mti", + "prost", + "serde", + "sp1-core-machine", + "sp1-hypercube", + "sp1-primitives", + "tokio", + "tonic", + "tonic-build", + "tracing", +] + +[[package]] +name = "sp1-recursion-circuit" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "itertools 0.14.0", + "rand 0.8.6", + "rayon", + "serde", + "slop-air", + "slop-algebra", + "slop-alloc", + "slop-basefold", + "slop-basefold-prover", + "slop-bn254", + "slop-challenger", + "slop-commit", + "slop-jagged", + "slop-koala-bear", + "slop-matrix", + "slop-merkle-tree", + "slop-multilinear", + "slop-stacked", + "slop-sumcheck", + "slop-symmetric", + "slop-tensor", + "slop-whir", + "sp1-core-executor", + "sp1-core-machine", + "sp1-derive", + "sp1-hypercube", + "sp1-primitives", + "sp1-recursion-compiler", + "sp1-recursion-executor", + "sp1-recursion-machine", + "tracing", +] + +[[package]] +name = "sp1-recursion-compiler" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "backtrace", + "cfg-if", + "itertools 0.14.0", + "serde", + "slop-algebra", + "slop-bn254", + "slop-symmetric", + "sp1-core-machine", + "sp1-hypercube", + "sp1-primitives", + "sp1-recursion-executor", + "tracing", + "vec_map", +] + +[[package]] +name = "sp1-recursion-executor" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "backtrace", + "cfg-if", + "hashbrown 0.14.5", + "itertools 0.14.0", + "range-set-blaze", + "serde", + "slop-algebra", + "slop-maybe-rayon", + "slop-poseidon2", + "slop-symmetric", + "smallvec", + "sp1-derive", + "sp1-hypercube", + "static_assertions", + "thiserror 1.0.69", + "tracing", +] + +[[package]] +name = "sp1-recursion-gnark-ffi" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "hex", + "num-bigint 0.4.6", + "serde", + "serde_json", + "sha2", + "slop-algebra", + "slop-symmetric", + "sp1-hypercube", + "sp1-primitives", + "sp1-recursion-compiler", + "sp1-verifier", + "tempfile", + "tracing", +] + +[[package]] +name = "sp1-recursion-machine" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "itertools 0.14.0", + "rand 0.8.6", + "slop-air", + "slop-algebra", + "slop-basefold", + "slop-matrix", + "slop-maybe-rayon", + "slop-symmetric", + "sp1-derive", + "sp1-hypercube", + "sp1-primitives", + "sp1-recursion-executor", + "strum", + "tracing", +] + +[[package]] +name = "sp1-sdk" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "cfg-if", + "dirs", + "eventsource-stream", + "futures", + "hex", + "indicatif", + "itertools 0.14.0", + "k256", + "num-bigint 0.4.6", + "serde", + "sha2", + "sp1-build", + "sp1-core-executor", + "sp1-core-executor-runner", + "sp1-core-machine", + "sp1-cuda", + "sp1-hypercube", + "sp1-primitives", + "sp1-prover", + "sp1-prover-types", + "sp1-recursion-executor", + "sp1-verifier", + "strum", + "tempfile", + "thiserror 1.0.69", + "tokio", + "tracing", +] + +[[package]] +name = "sp1-verifier" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "blake3", + "cfg-if", + "dirs", + "hex", + "lazy_static", + "serde", + "sha2", + "slop-algebra", + "slop-challenger", + "slop-primitives", + "slop-symmetric", + "sp1-hypercube", + "sp1-primitives", + "sp1-recursion-executor", + "sp1-recursion-machine", + "strum", + "substrate-bn-succinct-rs", + "thiserror 2.0.18", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "struct-reflection" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "701b671d1ad68e250e05718f95dae3014a17f4e69cbe51842531c30495ff3301" +dependencies = [ + "struct-reflection-derive", +] + +[[package]] +name = "struct-reflection-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ab74230a0592602e361bd63c645413fa8cbe4500d10274e849179e5c72548f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "subenum" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee3fb942ed39f3971438fcc7e05e20717e599e14c5c7cb50edd0df2a44b274" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "substrate-bn-succinct-rs" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a241fd7c1016fb8ad30fcf5a20986c0c4538e8f15a1b41a1761516299e377ec1" +dependencies = [ + "bytemuck", + "byteorder", + "cfg-if", + "crunchy", + "lazy_static", + "num-bigint 0.4.6", + "rand 0.8.6", + "rustc-hex", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "symlink" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7973cce6668464ea31f176d85b13c7ab3bba2cb3b77a2ed26abd7801688010a" + +[[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.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sysinfo" +version = "0.30.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5b4ddaee55fb2bea2bf0e5000747e5f5c0de765e5a5ff87f4cd106439f4bb3" +dependencies = [ + "cfg-if", + "core-foundation-sys", + "libc", + "ntapi", + "once_cell", + "rayon", + "windows", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom 0.4.2", + "once_cell", + "rustix", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2 0.6.3", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 0.6.11", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.25.11+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +dependencies = [ + "indexmap 2.14.0", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow 1.0.3", +] + +[[package]] +name = "tonic" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "prost", + "rustls-pemfile", + "socket2 0.5.10", + "tokio", + "tokio-rustls", + "tokio-stream", + "tower 0.4.13", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-build" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9557ce109ea773b399c9b9e5dca39294110b74f1f342cb347a80d1fce8c26a11" +dependencies = [ + "prettyplease", + "proc-macro2", + "prost-build", + "prost-types", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand 0.8.6", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", + "tower 0.5.3", + "tower-layer", + "tower-service", + "url", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-appender" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "050686193eb999b4bb3bc2acfa891a13da00f79734704c4b8b4ef1a10b368a3c" +dependencies = [ + "crossbeam-channel", + "symlink", + "thiserror 2.0.18", + "time", + "tracing-subscriber", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-forest" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" +dependencies = [ + "ansi_term", + "smallvec", + "thiserror 1.0.69", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "transpose" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" +dependencies = [ + "num-integer", + "strength_reduce", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "twox-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" + +[[package]] +name = "typeid_prefix" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9da1387307fdee46aa441e4f08a1b491e659fcac1aca9cd71f2c624a0de5d1b" + +[[package]] +name = "typeid_suffix" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77b55e96f110c6db5d1a2f24072552537f0091dc90cebeaa679540bac93e7405" +dependencies = [ + "uuid", +] + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +dependencies = [ + "atomic", + "getrandom 0.4.2", + "js-sys", + "md-5", + "sha1_smol", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +dependencies = [ + "serde", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen 0.57.1", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.122" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.14.0", + "wasm-encoder", + "wasmparser", +] + +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap 2.14.0", + "semver", +] + +[[package]] +name = "web-sys" +version = "0.3.99" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" +dependencies = [ + "rustls-pki-types", +] + +[[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-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.14.0", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap 2.14.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.14.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/sp1/Cargo.toml b/sp1/Cargo.toml new file mode 100644 index 00000000..91757491 --- /dev/null +++ b/sp1/Cargo.toml @@ -0,0 +1,6 @@ +[workspace] +members = ["host"] +# `guest/` is built via `sp1-build` for the RISC-V zkVM target and only +# compiles under `cargo-prove`; excluded so host workspace ops don't pick it up. +exclude = ["guest"] +resolver = "2" diff --git a/sp1/guest/Cargo.lock b/sp1/guest/Cargo.lock new file mode 100644 index 00000000..45d6d00e --- /dev/null +++ b/sp1/guest/Cargo.lock @@ -0,0 +1,1271 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addchain" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e33f6a175ec6a9e0aca777567f9ff7c3deefc255660df887e7fa3585e9801d8" +dependencies = [ + "num-bigint 0.3.3", + "num-integer", + "num-traits", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "bignat" +version = "0.1.0" +source = "git+https://github.com/argumentcomputer/lean-ffi.git?rev=839b405de708b80504fda39abe1402114b4135a5#839b405de708b80504fda39abe1402114b4135a5" +dependencies = [ + "num-bigint 0.4.6", +] + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake3" +version = "1.8.5" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "cpufeatures 0.3.0", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.62" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-default" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa" + +[[package]] +name = "constant_time_eq" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", + "rayon", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + +[[package]] +name = "embedded-alloc" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f2de9133f68db0d4627ad69db767726c99ff8585272716708227008d3f1bddd" +dependencies = [ + "const-default", + "critical-section", + "linked_list_allocator", + "rlsf", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "bitvec", + "byteorder", + "ff_derive", + "rand_core", + "subtle", +] + +[[package]] +name = "ff_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f10d12652036b0e99197587c6ba87a8fc3031986499973c030d8b44fcc151b60" +dependencies = [ + "addchain", + "num-bigint 0.3.3", + "num-integer", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "ix-common" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "indexmap", + "rustc-hash", +] + +[[package]] +name = "ix-kernel" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "dashmap", + "indexmap", + "itertools 0.14.0", + "ix-common", + "ixon", + "log", + "num-bigint 0.4.6", + "rayon", + "rustc-hash", +] + +[[package]] +name = "ixon" +version = "0.1.0" +dependencies = [ + "bignat", + "blake3", + "dashmap", + "indexmap", + "ix-common", + "memmap2", + "num-bigint 0.4.6", + "rayon", + "rustc-hash", + "sha2", + "tiny-keccak", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "linked_list_allocator" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b23ac50abb8261cb38c6e2a7192d3302e0836dac1628f6a93b82b4fad185897" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", +] + +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "p3-bn254-fr" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2077757c7cb514202ccb5368f521f23f5709c720599e6545c683c66e0a52d2d8" +dependencies = [ + "ff", + "num-bigint 0.4.6", + "p3-field", + "p3-poseidon2", + "p3-symmetric", + "rand", + "serde", +] + +[[package]] +name = "p3-challenger" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6a908924d43e4cfb93fb41c8346cac211b70314385a9037e9241f5b7f3eaf77" +dependencies = [ + "p3-field", + "p3-maybe-rayon", + "p3-symmetric", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-dft" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be6408b10a2c27eb13a7d5580c546c2179a8dc7dbc10a990657311891f9b41c0" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-field" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dc75969ca3ac847f43e632ab979d59ff7a68f9eac8dbf8edcbba47fc2e1d3aa" +dependencies = [ + "itertools 0.12.1", + "num-bigint 0.4.6", + "num-traits", + "p3-util", + "rand", + "serde", +] + +[[package]] +name = "p3-koala-bear" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9683cd0ef68100df7c62490533047bcf19c04c4a0fa1efc9d7c1e03e31f6b3" +dependencies = [ + "cfg-if", + "num-bigint 0.4.6", + "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", + "rand", + "rustc_version", + "serde", +] + +[[package]] +name = "p3-matrix" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75c3f150ceb90e09539413bf481e618d05ee19210b4e467d2902eb82d2e15281" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "p3-maybe-rayon", + "p3-util", + "rand", + "serde", + "tracing", +] + +[[package]] +name = "p3-maybe-rayon" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0641952b42da45e1dfa2d4a2a3163e330f944ad9740942f35026c0a71a605f1" + +[[package]] +name = "p3-mds" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa4a5f250e174dcfca5cbeac6ad75713924e7e7320e0a335e3c50b8b1f4fe8ec" +dependencies = [ + "itertools 0.12.1", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-symmetric", + "p3-util", + "rand", +] + +[[package]] +name = "p3-poseidon2" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "522986377b2164c5f94f2dae88e0e0a3d169cc6239202ef4aeb4322d60feffd0" +dependencies = [ + "gcd", + "p3-field", + "p3-mds", + "p3-symmetric", + "rand", + "serde", +] + +[[package]] +name = "p3-symmetric" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9047ce85c086a9b3f118e10078f10636f7bfeed5da871a04da0b61400af8793a" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "serde", +] + +[[package]] +name = "p3-util" +version = "0.4.3-succinct" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff962f8eaa5f36e0447cee7c241f6b4b475fadf3ee61f154327a26bb4e009ba" +dependencies = [ + "serde", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.17", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rlsf" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1646a59a9734b8b7a0ac51689388a60fe1625d4b956348e9de07591a1478457a" +dependencies = [ + "cfg-if", + "const-default", + "libc", + "rustversion", + "svgbobdoc", +] + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures 0.2.17", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "slop-algebra" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "itertools 0.14.0", + "p3-field", + "serde", +] + +[[package]] +name = "slop-bn254" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "ff", + "p3-bn254-fr", + "serde", + "slop-algebra", + "slop-challenger", + "slop-poseidon2", + "slop-symmetric", +] + +[[package]] +name = "slop-challenger" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "futures", + "p3-challenger", + "serde", + "slop-algebra", + "slop-symmetric", +] + +[[package]] +name = "slop-koala-bear" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "lazy_static", + "p3-koala-bear", + "serde", + "slop-algebra", + "slop-challenger", + "slop-poseidon2", + "slop-symmetric", +] + +[[package]] +name = "slop-poseidon2" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-poseidon2", +] + +[[package]] +name = "slop-primitives" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "slop-algebra", +] + +[[package]] +name = "slop-symmetric" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "p3-symmetric", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "sp1-guest" +version = "0.1.0" +dependencies = [ + "ix-common", + "ix-kernel", + "ixon", + "sp1-zkvm", +] + +[[package]] +name = "sp1-lib" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "serde", + "sp1-primitives", +] + +[[package]] +name = "sp1-primitives" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "bincode", + "blake3", + "elf", + "hex", + "itertools 0.14.0", + "lazy_static", + "num-bigint 0.4.6", + "serde", + "sha2", + "slop-algebra", + "slop-bn254", + "slop-challenger", + "slop-koala-bear", + "slop-poseidon2", + "slop-primitives", + "slop-symmetric", +] + +[[package]] +name = "sp1-zkvm" +version = "6.2.2" +source = "git+https://github.com/argumentcomputer/sp1?branch=blake3-precompile#ab7cda20b0e2f892bb5c5cb0ccf5c1ce5ba12c6b" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-alloc", + "getrandom 0.2.17", + "getrandom 0.3.4", + "lazy_static", + "libm", + "rand", + "sha2", + "sp1-lib", + "sp1-primitives", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "svgbobdoc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c04b93fc15d79b39c63218f15e3fdffaa4c227830686e3b7c5f41244eb3e50" +dependencies = [ + "base64", + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-width", +] + +[[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.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typenum" +version = "1.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.3+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] diff --git a/sp1/guest/Cargo.toml b/sp1/guest/Cargo.toml new file mode 100644 index 00000000..0c9587b0 --- /dev/null +++ b/sp1/guest/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "sp1-guest" +version = "0.1.0" +edition = "2024" + +[dependencies] +ixon = { path = "../../crates/ixon" } +ix-kernel = { path = "../../crates/kernel" } +ix-common = { path = "../../crates/common" } +sp1-zkvm = { git = "https://github.com/argumentcomputer/sp1", branch = "blake3-precompile" } + +# Force blake3 to the patched copy that routes `compress_in_place` / +# `compress_xof` through SP1's BLAKE3_COMPRESS precompile on the zkVM target. +# The guest's transitive blake3 (via ix-kernel) would otherwise resolve to +# the registry version because `sp1-build` doesn't extend the host workspace. +# +# Stays a local path because the patched blake3 fork hasn't been published to a +# git remote (no argumentcomputer/blake3 repo exists yet). Switch to a +# `git = ..., branch = "blake3-precompile"` ref once it's pushed. +[patch.crates-io] +blake3 = { path = "../../../blake3-sp1" } diff --git a/sp1/guest/src/main.rs b/sp1/guest/src/main.rs new file mode 100644 index 00000000..ff1e9207 --- /dev/null +++ b/sp1/guest/src/main.rs @@ -0,0 +1,192 @@ +//! SP1 guest binary: prove that every kernel-checkable constant in a +//! serialized Ixon environment typechecks under the Ix kernel. +//! +//! Input (two reads, in order): +//! 1. `u8`: kernel mode flag (0 = Anon default, 1 = Meta) via `read::`. +//! 2. `Vec`: Ixon-serialized environment via `read_vec`. +//! +//! Output (via `sp1_zkvm::io::commit_slice`, fixed 104-byte layout): +//! - `u32` failures (offset 0; 0 = all pass) +//! - `[u8; 32]` subject_root — canonical merkle root over the consts +//! this proof certified (Anon mode; zero in Meta) +//! - `[u8; 32]` assumptions_root — merkle root over their direct refs not +//! certified here (the conditional claim's external assumptions) +//! - `u32` checked_count +//! - `[u8; 32]` env_hash +//! +//! `(subject_root, assumptions_root)` form `Claim::CheckEnv { root, assumptions }` +//! — the same content-addressed conditional claim the Zisk leaf guest emits. +//! +//! Anon mode enumerates the work set in-guest via +//! [`ix_kernel::anon_work::build_anon_work`] — the same enumeration +//! that drives `rs_kernel_check_anon` in `crates/ffi/src/kernel.rs`. +//! The proof commits to "every kernel-checkable constant in this env +//! typechecks," matching Aiur's `kernel_check_test` semantics. +//! +//! Meta mode walks `env.named` for the kid set (preserves Lean names +//! + runs the dup-level-param-name check); slightly more constrained +//! and slightly more expensive in cycles. +//! +//! Both modes typecheck the same underlying structural set; they +//! differ only in which metadata fields the kernel carries through +//! `KEnv`. + +#![no_main] +sp1_zkvm::entrypoint!(main); + +use ix_common::address::Address; +use ix_kernel::anon_work::build_anon_work; +use ix_kernel::env::KEnv; +use ix_kernel::id::KId; +use ix_kernel::ingress::ixon_ingress_owned; +use ix_kernel::mode::{Anon, Meta}; +use ix_kernel::tc::TypeChecker; +use ixon::env::Env as IxonEnv; +use ixon::merkle::{merkle_root_canonical, zero_address}; +use ixon::metadata::ConstantMetaInfo; + +// SP1's cycle tracker (gated by the SDK `profiling` feature on the host +// side — see `sp1/host/Cargo.toml`) consumes `println!`s of the form +// `cycle-tracker-report-{start,end}: ` from stdout and accumulates +// total cycles per label across all invocations of that label. Each +// `println!` is a single `syscall_write`, so per-iteration brackets in +// hot loops add measurable overhead — keep these at coarse phase +// boundaries. To get per-constant cycle attribution (e.g. for a one-off +// "which `kid_NNN` dominates?" investigation), temporarily wrap the +// `tc.check_const(kid)` call below in the same pair of `println!`s; pair +// the output with `crates/kernel/examples/perf_check.rs` to map indices +// to constant names. +macro_rules! tic { ($name:expr) => { println!("cycle-tracker-report-start: {}", $name) } } +macro_rules! toc { ($name:expr) => { println!("cycle-tracker-report-end: {}", $name) } } + +pub fn main() { + let meta_mode: u8 = sp1_zkvm::io::read(); + let env_bytes: Vec = sp1_zkvm::io::read_vec(); + // `Address::hash` is blake3 via the precompile shim (same path the kernel + // uses) — binds the proof to the exact env payload. + let env_hash: [u8; 32] = *Address::hash(&env_bytes).as_bytes(); + + // Conditional-claim outputs: populated in Anon mode (the claim/resolution + // path, mirroring the Zisk leaf guest); left zero in Meta mode. + let mut subject_root = zero_address(); + let mut assumptions_root = zero_address(); + let mut checked_count: u32 = 0; + + let failures = if meta_mode == 1 { + // ---- Meta mode: full env load + eager ingress ---- + // + // `ixon_ingress_inner` walks `env.named` to enumerate work items, + // so we need the full env (with the metadata sections intact). + tic!("ixon_decode_env"); + let env = + IxonEnv::get(&mut &env_bytes[..]).expect("invalid Ixon environment"); + toc!("ixon_decode_env"); + + let mut kids: Vec> = Vec::with_capacity(env.named.len()); + kids.extend( + env + .named + .iter() + .filter(|e| !matches!(e.value().meta.info, ConstantMetaInfo::Muts { .. })) + .map(|e| KId::::new(e.value().addr.clone(), e.key().clone())), + ); + + tic!("ingress"); + let (mut kenv, _intern) = + ixon_ingress_owned::(env).expect("ingress failed"); + toc!("ingress"); + + let mut failures: u32 = 0; + tic!("check_const_loop"); + let mut tc = TypeChecker::new(&mut kenv); + for kid in &kids { + if tc.check_const(kid).is_err() { + failures = failures.saturating_add(1); + } + } + toc!("check_const_loop"); + failures + } else { + // ---- Anon mode: get_anon + lazy on-demand ingress ---- + // + // `Env::get_anon` parses-and-discards the metadata sections + // (named/names/comms) so the steady-state env carries only + // `consts`/`blobs`/`anon_hints`. `build_anon_work` enumerates the + // canonical kernel-checkable work set from `env.consts` alone + // (no metadata) — same logic the FFI's `rs_kernel_check_anon` + // uses. Each `tc.check_const(primary)` either typechecks one + // standalone or drives the kernel's block coordination to cover + // every member + ctor of a Muts block. + tic!("ixon_decode_env"); + let env = + IxonEnv::get_anon(&mut &env_bytes[..]).expect("invalid Ixon environment"); + toc!("ixon_decode_env"); + + tic!("build_anon_work"); + let work = build_anon_work(&env).expect("build_anon_work"); + toc!("build_anon_work"); + + let mut kenv = KEnv::::new(); + let mut failures: u32 = 0; + let mut checked_covered: Vec
= Vec::new(); + tic!("check_const_loop"); + let mut tc = TypeChecker::::new_with_lazy_anon(&mut kenv, &env); + for item in &work { + let kid = KId::::new(item.primary().clone(), ()); + if tc.check_const(&kid).is_err() { + failures = failures.saturating_add(1); + } + // Certify in `consts`-key space (block addr + projections) — the same + // address space `Constant.refs` use, so the assumption set and its + // cross-proof resolution line up. + checked_covered.extend(item.proven_targets()); + } + toc!("check_const_loop"); + + // ---- Conditional claim: CheckEnv { subject, assumptions } ---- + // + // subject = canonical merkle root over the consts certified here. + // assumptions = canonical merkle root over their DIRECT refs not + // certified here — this whole-env proof's external dependencies + // (ultimately the declared axioms). Mirrors the Zisk leaf guest so + // both backends emit the same content-addressed claim. + // + // A `Constant.refs` entry points at either another CONSTANT (a genuine + // typing obligation) or a literal DATA blob (the bytes behind an + // `Expr::Nat`/`Expr::Str` — e.g. the numbers 0, 1). Literals are + // well-typed by construction with content-pinned bytes, so they are NOT + // assumptions; skip refs that resolve to a blob (must match Zisk). + tic!("claim_roots"); + checked_count = checked_covered.len() as u32; + subject_root = + merkle_root_canonical(&checked_covered).unwrap_or_else(zero_address); + let mut sorted = checked_covered.clone(); + sorted.sort_unstable(); + sorted.dedup(); + let mut assumptions: Vec
= Vec::new(); + for t in &checked_covered { + if let Some(c) = env.get_const(t) { + for r in &c.refs { + if sorted.binary_search(r).is_err() && env.get_blob(r).is_none() { + assumptions.push(r.clone()); + } + } + } + } + assumptions_root = + merkle_root_canonical(&assumptions).unwrap_or_else(zero_address); + toc!("claim_roots"); + failures + }; + + // Fixed 104-byte public output: failures(4) + subject_root(32) + + // assumptions_root(32) + checked_count(4) + env_hash(32). `failures` stays + // at offset 0 so existing readers keep working. + let mut out = Vec::with_capacity(104); + out.extend_from_slice(&failures.to_le_bytes()); + out.extend_from_slice(subject_root.as_bytes()); + out.extend_from_slice(assumptions_root.as_bytes()); + out.extend_from_slice(&checked_count.to_le_bytes()); + out.extend_from_slice(&env_hash); + sp1_zkvm::io::commit_slice(&out); +} diff --git a/sp1/host/Cargo.toml b/sp1/host/Cargo.toml new file mode 100644 index 00000000..f45c1d3c --- /dev/null +++ b/sp1/host/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "sp1-host" +version = "0.1.0" +edition = "2024" +default-run = "sp1-host" + +[[bin]] +name = "sp1-host" +path = "src/main.rs" + +[dependencies] +ixon = { path = "../../crates/ixon" } +ix-common = { path = "../../crates/common" } +# Used only to count work items for human-readable output via +# `build_anon_work` — same enumeration the guest runs in-circuit. +ix-kernel = { path = "../../crates/kernel" } +# `profiling` turns on the SP1 executor's cycle-tracker: it reads +# `cycle-tracker-report-{start,end}: