Expand description
§ryo-source
High-speed Rust AST manipulation engine for the RYO (流) project’s “Fluid Code” paradigm.
This crate provides two complementary AST representations optimized for different use cases:
RustAST for full-fidelity manipulation and PureFile for thread-safe parallel processing.
§Core Philosophy: Fluid Code
Code is not static text—it’s a living, flowing structure that can be manipulated, analyzed, and transformed at high speed. The AST is the “shadow” of source code, a pure representation that enables:
- Instant Analysis: Query definitions, references, and dependencies in nanoseconds
- Safe Mutation: Transform code with type-safe operations
- Parallel Processing: Share and analyze code across threads via
PureFile
§Dual AST Architecture
Source Code
"fn main() { ... }"
│
▼
syn::parse
│
┌───────────────┴───────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ RustAST │ │ PureFile │
│ (Full-fidelity)│ │ (Thread-safe) │
├─────────────────┤ ├─────────────────┤
│ • syn::File │ │ • Span-free │
│ • Complete info │ ToPure │ • Send + Sync │
│ • Span preserve │ ───────▶ │ • Arc-shareable │
│ • Code gen │ (~10%) │ • Serializable │
│ • NOT Send/Sync │ │ • Lightweight │
└─────────────────┘ └─────────────────┘§RustAST: Full-Fidelity AST
RustAST wraps syn::File to provide high-level operations while preserving
complete syntactic information including spans (source locations).
use ryo_source::RustAST;
// Parse source code
let mut ast = RustAST::parse("use std::io;\nfn main() {}").unwrap();
// Remove unused imports
let removed = ast.remove_unused_imports();
assert_eq!(removed.len(), 1);
// Generate cleaned code
let code = ast.to_string_pretty();
assert!(!code.contains("use std::io"));§PureFile: Thread-Safe AST
PureFile strips all Span information, creating a pure data structure
that can be safely shared across threads with Arc.
use std::sync::Arc;
use std::thread;
use ryo_source::PureFile;
// Parse directly to PureFile
let pure = PureFile::from_source("fn foo() {} fn bar() {}").unwrap();
// Share across threads
let shared = Arc::new(pure);
let s1 = Arc::clone(&shared);
let h1 = thread::spawn(move || s1.functions().len());
let s2 = Arc::clone(&shared);
let h2 = thread::spawn(move || s2.find_fn("foo").is_some());
assert_eq!(h1.join().unwrap(), 2);
assert!(h2.join().unwrap());§Operations
§Query Operations (Read-only)
| Operation | Description |
|---|---|
DefRefs::analyze | Find all symbol definitions and references |
DefRefs::find_definition | Locate where a symbol is defined |
DefRefs::find_references | Find all uses of a symbol |
PureFile::functions | Get all functions (thread-safe) |
PureFile::find_fn | Find function by name (thread-safe) |
§Mutation Operations
| Operation | Description | Pattern |
|---|---|---|
Rename::apply | Rename symbols globally | In-place |
Rename::rename_local_in_fn | Rename within specific function | In-place |
RemoveUnusedImports::apply | Remove unused imports | In-place |
CowMut::rename | Copy-on-write rename | Returns new AST |
CowMut::chain_renames | Sequential renames | Returns new AST |
§Copy-on-Write Mutation
For scenarios requiring multiple independent mutations:
use ryo_source::{RustAST, CowMut};
let ast = RustAST::parse("fn foo() { fn bar() {} }").unwrap();
// Each rename produces an independent copy
let results = CowMut::multi_rename(&ast, &[
("foo", "alpha"),
("bar", "beta"),
]);
// results[0].ast has foo→alpha, bar unchanged
// results[1].ast has bar→beta, foo unchanged
// Original ast is unchanged
assert!(ast.to_string().contains("foo"));§Why syn over tree-sitter?
We chose syn for Rust because:
- Semantic Awareness: syn understands Rust’s semantics, not just syntax
- Type Safety: Operations are checked at compile time
- Ecosystem Integration: Works with
quote,proc-macro2, and Rust tooling - Rust-First Philosophy: Optimized for Rust’s unique features
Re-exports§
pub use generator::GeneratedFiles;pub use generator::GeneratedSource;pub use generator::ModuleTree;pub use generator::MultiFileGenerator;pub use generator::SingleFileGenerator;pub use generator::SourceGenerator;pub use ops::DefRefs;pub use ops::Location;pub use ops::RemoveUnusedImports;pub use ops::Rename;pub use ops::RenameResult;pub use ops::Symbol;pub use ops::SymbolKind;pub use ops::SymbolTable;pub use parallel::CowMut;pub use parallel::MutResult;pub use parallel::SourceParallel;pub use pure::ItemKind;pub use pure::PureFile;pub use pure::ToPure;pub use pure::ToSyn;
Modules§
- generator
- Source code generation from Pure AST.
- ops
- AST operations (Surgeon actions).
- parallel
- Parallel access patterns for RustAST and PureFile.
- pure
- PureAST - Thread-safe, Span-free AST for parallel processing.
Structs§
- RustAST
- Rust source code with parsed AST.
Enums§
- Source
Error - Errors that can occur during AST manipulation.
Type Aliases§
- Source
Result - Result type for source operations.