From bca32682ec0ffa018bde8fc89091be62c29308c6 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 21:15:05 +0000 Subject: [PATCH 1/5] ruff_r2il: build against r2il's resolved/aliased address spaces The r2sleigh `r2il` crate added `AddressSpace::aliases` and the `SpaceId::Unresolved` variant, a space the lifter could not name. Every unresolved space compares equal, so it has no stable identity to project. - `facet::project` refuses an unresolved space with the new `FacetOverflow::UnresolvedSpace` instead of assigning it a discriminant, which would merge spaces that may be distinct. - The furnace records such a varnode as the new `ResidualReason::UnresolvedSpace` (anchored at the enclosing block, like an unknown custom space), and the ledger sink writes and parses it. - The oracle's permissive arch builds its custom spaces with `aliases: None` ("not known to alias anything"). - The corpus profile counts unresolved-space projections separately. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017HJA9obVWqSQYNtXGnMGLd --- .../ruff_r2il/examples/r2il_corpus_profile.rs | 13 ++++++--- crates/ruff_r2il/src/facet.rs | 27 +++++++++++++++++++ crates/ruff_r2il/src/furnace.rs | 12 +++++++++ crates/ruff_r2il/src/oracle.rs | 1 + crates/ruff_r2il/src/sink.rs | 2 ++ crates/ruff_r2il/src/slag.rs | 13 +++++++-- 6 files changed, 63 insertions(+), 5 deletions(-) diff --git a/crates/ruff_r2il/examples/r2il_corpus_profile.rs b/crates/ruff_r2il/examples/r2il_corpus_profile.rs index 8e184185aae0c..9ca6ce4dba34d 100644 --- a/crates/ruff_r2il/examples/r2il_corpus_profile.rs +++ b/crates/ruff_r2il/examples/r2il_corpus_profile.rs @@ -661,6 +661,7 @@ struct Pass2Stats { vocab_interned_id_bytes: Vec, facet_ok: usize, facet_unknown_custom_space: usize, + facet_unresolved_space: usize, facet_ordinal_exhausted: usize, smelt_harvested: usize, smelt_classified: usize, @@ -723,12 +724,15 @@ fn print_pass2(stats: &Pass2Stats) { print_distribution("vocab.ssa_name_bytes", &stats.vocab_ssa_name_bytes); print_distribution("vocab.interned_id_bytes", &stats.vocab_interned_id_bytes); - let facet_total = - stats.facet_ok + stats.facet_unknown_custom_space + stats.facet_ordinal_exhausted; + let facet_total = stats.facet_ok + + stats.facet_unknown_custom_space + + stats.facet_unresolved_space + + stats.facet_ordinal_exhausted; println!( - " facet::project sweep: ok={} FacetOverflow(UnknownCustomSpace)={} FacetOverflow(CustomOrdinalExhausted)={} total={}", + " facet::project sweep: ok={} FacetOverflow(UnknownCustomSpace)={} FacetOverflow(UnresolvedSpace)={} FacetOverflow(CustomOrdinalExhausted)={} total={}", stats.facet_ok, stats.facet_unknown_custom_space, + stats.facet_unresolved_space, stats.facet_ordinal_exhausted, facet_total ); @@ -932,6 +936,9 @@ fn run_pass2_over( Err(facet::FacetOverflow::UnknownCustomSpace { .. }) => { stats.facet_unknown_custom_space += 1; } + Err(facet::FacetOverflow::UnresolvedSpace) => { + stats.facet_unresolved_space += 1; + } Err(facet::FacetOverflow::CustomOrdinalExhausted { .. }) => { stats.facet_ordinal_exhausted += 1; } diff --git a/crates/ruff_r2il/src/facet.rs b/crates/ruff_r2il/src/facet.rs index 20c9144afb9a9..b021c639283a0 100644 --- a/crates/ruff_r2il/src/facet.rs +++ b/crates/ruff_r2il/src/facet.rs @@ -125,6 +125,11 @@ pub enum FacetOverflow { /// back to `raw as u16` (`65541` and `5` both truncate to `5`, silently colliding two /// distinct architecture-defined spaces). UnknownCustomSpace { raw: u32 }, + /// The varnode's space is `SpaceId::Unresolved`: the lifter could not name it, so it has + /// no stable discriminant. Projection REFUSES rather than assign one, because every + /// unresolved space compares equal and a shared discriminant would merge spaces that may + /// be distinct. + UnresolvedSpace, /// The set of distinct custom-space raw ids exceeds [`MAX_CUSTOM_ORDINAL`]. Overflow is /// EVIDENCE a route needs factoring, never silent truncation (the `mint_factored` /// principle). @@ -137,6 +142,12 @@ impl core::fmt::Display for FacetOverflow { FacetOverflow::UnknownCustomSpace { raw } => { write!(f, "custom space {raw} is not in the interned table") } + FacetOverflow::UnresolvedSpace => { + write!( + f, + "the varnode's address space was not resolved by the lifter" + ) + } FacetOverflow::CustomOrdinalExhausted { count } => { write!( f, @@ -228,6 +239,7 @@ pub fn project(vn: &Varnode, spaces: &CustomSpaceTable) -> Result spaces .ordinal_of(raw) .ok_or(FacetOverflow::UnknownCustomSpace { raw })?, + SpaceId::Unresolved => return Err(FacetOverflow::UnresolvedSpace), }; let classid = ((PROVISIONAL_R2IL_VARNODE as u32) << 16) | discriminant as u32; let offset_lo = (vn.offset & 0xFFFF_FFFF) as u32; @@ -305,6 +317,21 @@ mod tests { assert_eq!(back, vn); } + #[test] + fn unresolved_space_is_refused_rather_than_given_a_discriminant() { + // Every unresolved space compares equal, so no table, however populated, can + // give one a discriminant without risking a merge of two different spaces. + let table = CustomSpaceTable::from_ids([0, 5]).expect("2 ids is within budget"); + let vn = Varnode::new(SpaceId::Unresolved, 0x10, 4); + assert_eq!(project(&vn, &table), Err(FacetOverflow::UnresolvedSpace)); + assert_eq!( + project(&vn, &CustomSpaceTable::default()), + Err(FacetOverflow::UnresolvedSpace) + ); + // The same offset and size in a named space still projects. + assert!(project(&Varnode::new(SpaceId::Ram, 0x10, 4), &table).is_ok()); + } + #[test] fn custom_space_outside_the_table_errors_and_never_truncates() { let empty = CustomSpaceTable::default(); diff --git a/crates/ruff_r2il/src/furnace.rs b/crates/ruff_r2il/src/furnace.rs index dc8273a457eee..8e8cbe73080ed 100644 --- a/crates/ruff_r2il/src/furnace.rs +++ b/crates/ruff_r2il/src/furnace.rs @@ -391,6 +391,18 @@ pub fn smelt( prov, ); } + Err(FacetOverflow::UnresolvedSpace) => { + // Same fallback as an unknown custom space: the residual is anchored + // at the enclosing op's block so it still carries an address. + let at = any_anchor_facet(behavior, prov, conv); + push_named_residual( + &mut ledger, + ResidualReason::UnresolvedSpace, + at, + conv, + prov, + ); + } Err(FacetOverflow::CustomOrdinalExhausted { count }) => { // Structurally unreachable for a validly-constructed `CustomSpaceTable` // (the budget is enforced at `from_ids`/`from_arch` time) — handled diff --git a/crates/ruff_r2il/src/oracle.rs b/crates/ruff_r2il/src/oracle.rs index 1320f9ac81021..858f966820631 100644 --- a/crates/ruff_r2il/src/oracle.rs +++ b/crates/ruff_r2il/src/oracle.rs @@ -479,6 +479,7 @@ pub fn permissive_convention(blocks: &[R2ILBlock]) -> Result (String, String) { (expected.as_str().to_string(), found.as_str().to_string()) } ResidualReason::NoConventionRowAtAddress + | ResidualReason::UnresolvedSpace | ResidualReason::MemoryObjectEscaped | ResidualReason::IndirectTarget | ResidualReason::NoFacetCoordinate => (String::new(), String::new()), @@ -526,6 +527,7 @@ fn parse_reason(name: &str, p1: &str, p2: &str) -> io::Result { "custom_space_not_in_convention" => ResidualReason::CustomSpaceNotInConvention { raw: parse_u32(p1)?, }, + "unresolved_space" => ResidualReason::UnresolvedSpace, "facet_overflow_at_key" => ResidualReason::FacetOverflowAtKey { raw: parse_u32(p1)?, }, diff --git a/crates/ruff_r2il/src/slag.rs b/crates/ruff_r2il/src/slag.rs index a4481376c0edf..dd3f578799bee 100644 --- a/crates/ruff_r2il/src/slag.rs +++ b/crates/ruff_r2il/src/slag.rs @@ -90,6 +90,10 @@ pub enum ResidualReason { /// The varnode's `SpaceId::Custom(raw)` is not in the convention's /// [`crate::facet::CustomSpaceTable`]. CustomSpaceNotInConvention { raw: u32 }, + /// The varnode's space is `SpaceId::Unresolved`: the lifter could not name it, + /// so no stable facet coordinate exists for it. Every such varnode compares + /// equal, so there is no payload to distinguish them. + UnresolvedSpace, /// The `Custom(raw)` space exists in the arch data but exceeds the /// interned-ordinal budget at CONFIG-KEY construction time (§4's /// promoted falsifier) — a typed overflow, never a silent truncation. @@ -126,6 +130,7 @@ impl ResidualReason { "no_convention_row_at_address", "userop_not_in_convention", "custom_space_not_in_convention", + "unresolved_space", "facet_overflow_at_key", "variadic_arity", "phi_fan_in_exceeds_predecessors", @@ -143,6 +148,7 @@ impl ResidualReason { ResidualReason::NoConventionRowAtAddress => "no_convention_row_at_address", ResidualReason::UserOpNotInConvention { .. } => "userop_not_in_convention", ResidualReason::CustomSpaceNotInConvention { .. } => "custom_space_not_in_convention", + ResidualReason::UnresolvedSpace => "unresolved_space", ResidualReason::FacetOverflowAtKey { .. } => "facet_overflow_at_key", ResidualReason::VariadicArity { .. } => "variadic_arity", ResidualReason::PhiFanInExceedsPredecessors { .. } => "phi_fan_in_exceeds_predecessors", @@ -172,6 +178,7 @@ impl ResidualReason { ResidualReason::CustomSpaceNotInConvention { raw } => { bytes.extend_from_slice(&raw.to_le_bytes()); } + ResidualReason::UnresolvedSpace => {} ResidualReason::FacetOverflowAtKey { raw } => { bytes.extend_from_slice(&raw.to_le_bytes()); } @@ -463,13 +470,14 @@ mod tests { // `ResidualReason`, this fails to COMPILE until this test (and // `ResidualReason::ALL`) are updated to match. That non-compiling // failure mode is the falsifier for "no catch-all reason". - let sample: [ResidualReason; 11] = [ + let sample: [ResidualReason; 12] = [ ResidualReason::OpcodeNotInConvention { opcode: OpTag::Copy, }, ResidualReason::NoConventionRowAtAddress, ResidualReason::UserOpNotInConvention { userop: 0 }, ResidualReason::CustomSpaceNotInConvention { raw: 0 }, + ResidualReason::UnresolvedSpace, ResidualReason::FacetOverflowAtKey { raw: 0 }, ResidualReason::VariadicArity { arity: 0 }, ResidualReason::PhiFanInExceedsPredecessors { @@ -492,6 +500,7 @@ mod tests { ResidualReason::NoConventionRowAtAddress => 1, ResidualReason::UserOpNotInConvention { .. } => 1, ResidualReason::CustomSpaceNotInConvention { .. } => 1, + ResidualReason::UnresolvedSpace => 1, ResidualReason::FacetOverflowAtKey { .. } => 1, ResidualReason::VariadicArity { .. } => 1, ResidualReason::PhiFanInExceedsPredecessors { .. } => 1, @@ -502,7 +511,7 @@ mod tests { // Deliberately NO `_ =>` arm. }; } - assert_eq!(variant_count, 11); + assert_eq!(variant_count, 12); assert_eq!(ResidualReason::ALL.len(), variant_count); let mut sorted = ResidualReason::ALL.to_vec(); From 167910b028cde6c12c93a76ab0be68eb4b6a889e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 21:15:05 +0000 Subject: [PATCH 2/5] ci: format, lint and test ruff_r2il `ruff_r2il` is excluded from the workspace because it path-depends on the `r2sleigh` and `a2ui-rs` checkouts next to this repository, so the workspace-wide fmt, clippy and test jobs never built it, and it had stopped compiling against the current `r2il` without any check noticing. The new `cargo (ruff_r2il)` job checks out both siblings beside this repository, then runs `cargo fmt --check`, clippy with warnings denied (with and without the `lift` feature) and `cargo test`, all `--locked` on the repository's toolchain. It is part of the "all required checks passed" gate. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017HJA9obVWqSQYNtXGnMGLd --- .github/workflows/ci.yaml | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5899c0ec77400..0c2fc1bfdeecc 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -656,6 +656,54 @@ jobs: MSRV: ${{ steps.msrv.outputs.value }} run: cargo "+${MSRV}" test --no-run --all-features + cargo-r2il: + # `ruff_r2il` (fork-only) is excluded from the workspace because it path-depends + # on the `r2sleigh` and `a2ui-rs` sibling checkouts, so the workspace-wide fmt, + # clippy and test jobs never reach it. This job checks out both siblings next to + # this repository, matching the `../../../` paths in its Cargo.toml. + name: "cargo (ruff_r2il)" + runs-on: ubuntu-latest + needs: determine_changes + if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} + timeout-minutes: 30 + env: + CARGO_PROFILE_DEV_DEBUG: line-tables-only + R2IL_MANIFEST: crates/ruff_r2il/Cargo.toml + defaults: + run: + working-directory: ruff + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: ruff + persist-credentials: false + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: AdaWorldAPI/r2sleigh + path: r2sleigh + persist-credentials: false + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: AdaWorldAPI/a2ui-rs + path: a2ui-rs + persist-credentials: false + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 + with: + workspaces: ruff/crates/ruff_r2il + save-if: ${{ github.ref == 'refs/heads/main' }} + - name: "Install Rust toolchain" + run: rustup component add rustfmt clippy + - name: "Install mold" + uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 + - name: "cargo fmt" + run: cargo fmt --manifest-path "${R2IL_MANIFEST}" --check + - name: "cargo clippy" + run: cargo clippy --manifest-path "${R2IL_MANIFEST}" --all-targets --locked -- -D warnings + - name: "cargo clippy (lift)" + run: cargo clippy --manifest-path "${R2IL_MANIFEST}" --features lift --all-targets --locked -- -D warnings + - name: "cargo test" + run: cargo test --manifest-path "${R2IL_MANIFEST}" --locked + cargo-fuzz-build: name: "cargo fuzz build" runs-on: ${{ github.repository == 'astral-sh/ruff' && 'github-ubuntu-24.04-x86_64-4' || 'ubuntu-latest' }} @@ -1537,6 +1585,7 @@ jobs: - cargo-test-linux - cargo-test-wasm - cargo-build-msrv + - cargo-r2il - shellcheck - scripts - prek From 02da34be38d34b156bd56a636f25e16d51f56d3e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 21:20:39 +0000 Subject: [PATCH 3/5] hawk: treat the fork's SPO/transcode libraries as product boundaries `cargo hawk` reports public items that nothing in the workspace outside the crate uses. The fork's SPO/transcode crates are libraries whose public API is consumed outside this workspace (OGAR and the transcode consumers), so every one of their exported items was reported: 455 findings, all in these nine crates. Each is now listed as a `[[production]]` library, which tells hawk its public API is an external boundary. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017HJA9obVWqSQYNtXGnMGLd --- hawk.toml | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/hawk.toml b/hawk.toml index 24fca67797055..430922a8fa925 100644 --- a/hawk.toml +++ b/hawk.toml @@ -32,6 +32,54 @@ package = "ty_completion_eval" bin = "ty_completion_eval" reason = "workspace completion evaluation binary" +# Fork-only SPO/transcode libraries. Their public API is consumed outside this +# workspace (OGAR and the transcode consumers), so it is a product boundary. + +[[production]] +package = "ruff_cpp_codegen" +lib = "ruff_cpp_codegen" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_cpp_spo" +lib = "ruff_cpp_spo" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_csharp_spo" +lib = "ruff_csharp_spo" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_python_dto_check" +lib = "ruff_python_dto_check" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_python_spo" +lib = "ruff_python_spo" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_ruby_spo" +lib = "ruff_ruby_spo" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_spo_address" +lib = "ruff_spo_address" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_spo_triplet" +lib = "ruff_spo_triplet" +reason = "fork SPO/transcode library consumed outside this workspace" + +[[production]] +package = "ruff_sqlalchemy_spo" +lib = "ruff_sqlalchemy_spo" +reason = "fork SPO/transcode library consumed outside this workspace" + # Keep this list in sync with workspace packages that define doctests. [[doctest]] From 7a74b4672c1b7dc024eedf550132f34d1815e4d3 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 21:40:27 +0000 Subject: [PATCH 4/5] ci: exclude the fork SPO libraries from hawk as external API Declaring the nine fork SPO/transcode crates as `[[production]]` lib targets did not help. Hawk still audits a production library: a public item with no use inside the workspace is reported as dead or unnecessarily public, so 422 findings remained. These crates are called from outside this workspace (OGAR and the transcode consumers), which a closed-world analysis cannot see. Hawk's documented mechanism for that case is `--exclude-crate`: the crates are still compiled, but their public declarations are not reported. Revert the `[[production]]` entries and pass the flag for each crate in the CI step. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017HJA9obVWqSQYNtXGnMGLd --- .github/workflows/ci.yaml | 16 ++++++++++++- hawk.toml | 48 --------------------------------------- 2 files changed, 15 insertions(+), 49 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 0c2fc1bfdeecc..3b15097ce40c6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -385,7 +385,21 @@ jobs: curl --proto '=https' --tlsv1.2 -LsSf \ "https://github.com/astral-sh/hawk/releases/download/${HAWK_VERSION}/cargo-hawk-installer.sh" | sh - name: "Hawk" - run: cargo +1.99.0 hawk check --target-dir target/hawk --color=always -D warnings + # The fork SPO/transcode libraries are an external API: OGAR and the + # transcode consumers call them from outside this workspace, which a + # closed-world analysis cannot see. Hawk compiles them but does not + # report their public declarations. + run: >- + cargo +1.99.0 hawk check --target-dir target/hawk --color=always -D warnings + --exclude-crate ruff_cpp_codegen + --exclude-crate ruff_cpp_spo + --exclude-crate ruff_csharp_spo + --exclude-crate ruff_python_dto_check + --exclude-crate ruff_python_spo + --exclude-crate ruff_ruby_spo + --exclude-crate ruff_spo_address + --exclude-crate ruff_spo_triplet + --exclude-crate ruff_sqlalchemy_spo cargo-publish-dry-run: name: "cargo publish dry-run" diff --git a/hawk.toml b/hawk.toml index 430922a8fa925..24fca67797055 100644 --- a/hawk.toml +++ b/hawk.toml @@ -32,54 +32,6 @@ package = "ty_completion_eval" bin = "ty_completion_eval" reason = "workspace completion evaluation binary" -# Fork-only SPO/transcode libraries. Their public API is consumed outside this -# workspace (OGAR and the transcode consumers), so it is a product boundary. - -[[production]] -package = "ruff_cpp_codegen" -lib = "ruff_cpp_codegen" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_cpp_spo" -lib = "ruff_cpp_spo" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_csharp_spo" -lib = "ruff_csharp_spo" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_python_dto_check" -lib = "ruff_python_dto_check" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_python_spo" -lib = "ruff_python_spo" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_ruby_spo" -lib = "ruff_ruby_spo" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_spo_address" -lib = "ruff_spo_address" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_spo_triplet" -lib = "ruff_spo_triplet" -reason = "fork SPO/transcode library consumed outside this workspace" - -[[production]] -package = "ruff_sqlalchemy_spo" -lib = "ruff_sqlalchemy_spo" -reason = "fork SPO/transcode library consumed outside this workspace" - # Keep this list in sync with workspace packages that define doctests. [[doctest]] From 4d4bd843496ba3bac5acba53db2a8e71c0712c1b Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 21:47:06 +0000 Subject: [PATCH 5/5] ruff_r2il: update the lockfile for upstream r2sleigh The fork of r2sleigh was replayed onto radareorg/r2sleigh master. There, the lifter depends on `r2source` and `roxmltree` and no longer on `thiserror`, so the `--locked` builds in the `cargo (ruff_r2il)` job refused the old lockfile. This records the minimal update cargo makes against the replayed tree; no other version moves. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_017HJA9obVWqSQYNtXGnMGLd --- crates/ruff_r2il/Cargo.lock | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/crates/ruff_r2il/Cargo.lock b/crates/ruff_r2il/Cargo.lock index e8d146d16819a..ff3d0525d499d 100644 --- a/crates/ruff_r2il/Cargo.lock +++ b/crates/ruff_r2il/Cargo.lock @@ -375,6 +375,12 @@ dependencies = [ "rawpointer", ] +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + [[package]] name = "ndarray" version = "0.17.2" @@ -508,10 +514,19 @@ version = "0.1.0" dependencies = [ "libsla", "r2il", - "sleigh-config", + "r2source", + "roxmltree", "thiserror", ] +[[package]] +name = "r2source" +version = "0.1.0" +dependencies = [ + "r2il", + "serde", +] + [[package]] name = "r2ssa" version = "0.1.0" @@ -519,8 +534,8 @@ dependencies = [ "petgraph", "r2il", "r2sleigh-lift", + "r2source", "serde", - "thiserror", ] [[package]] @@ -529,6 +544,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" +[[package]] +name = "roxmltree" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb" +dependencies = [ + "memchr", +] + [[package]] name = "ruff_r2il" version = "0.1.0"