Skip to main content

Crate ryo_source

Crate ryo_source 

Source
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)

OperationDescription
DefRefs::analyzeFind all symbol definitions and references
DefRefs::find_definitionLocate where a symbol is defined
DefRefs::find_referencesFind all uses of a symbol
PureFile::functionsGet all functions (thread-safe)
PureFile::find_fnFind function by name (thread-safe)

§Mutation Operations

OperationDescriptionPattern
Rename::applyRename symbols globallyIn-place
Rename::rename_local_in_fnRename within specific functionIn-place
RemoveUnusedImports::applyRemove unused importsIn-place
CowMut::renameCopy-on-write renameReturns new AST
CowMut::chain_renamesSequential renamesReturns 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:

  1. Semantic Awareness: syn understands Rust’s semantics, not just syntax
  2. Type Safety: Operations are checked at compile time
  3. Ecosystem Integration: Works with quote, proc-macro2, and Rust tooling
  4. 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§

SourceError
Errors that can occur during AST manipulation.

Type Aliases§

SourceResult
Result type for source operations.