Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mtshiba/ruast
Printable & modifiable Rust AST library
https://github.com/mtshiba/ruast
ast compiler library rust
Last synced: 3 months ago
JSON representation
Printable & modifiable Rust AST library
- Host: GitHub
- URL: https://github.com/mtshiba/ruast
- Owner: mtshiba
- License: apache-2.0
- Created: 2023-07-01T03:32:42.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-10-24T15:22:33.000Z (3 months ago)
- Last Synced: 2024-10-25T13:49:11.855Z (3 months ago)
- Topics: ast, compiler, library, rust
- Language: Rust
- Homepage: https://docs.rs/ruast/
- Size: 191 KB
- Stars: 5
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# `ruast`
This crate provides a printable & modifiable Rust AST.
## Basic usage
### Hello world
```rust
use ruast::*;let mut krate = Crate::new();
let def = Fn::main(
None,
Block::from(
Path::single("println")
.mac_call(vec![Token::lit("Hello, world!")])
.semi(),
),
);
krate.add_item(def);
println!("{krate}");
// krate.dump("test.rs")?;
// krate.compile("test.rs", CompileOptions::default())?;
krate.remove_item_by_id("main");
assert!(krate.is_empty());
```This is equivalent to:
```rust
use ruast::*;let mut krate = Crate::new();
krate.add_item(Fn {
is_unsafe: false,
is_const: false,
is_async: false,
abi: None,
ident: "main".to_string(),
generics: vec![],
fn_decl: FnDecl::new(vec![], None),
body: Some(Block::from(Stmt::Semi(Semi::new(Expr::new(MacCall {
path: Path::single("println"),
args: DelimArgs::from(vec![Token::lit("Hello, world!")]),
}))))),
});
println!("{krate}");
// krate.dump("test.rs")?;
// krate.compile("test.rs", CompileOptions::default())?;
krate.remove_item_by_id("main");
assert!(krate.is_empty());
``````rust
> cargo run --example hellofn main() {
println!("Hello, world!");
}
```### Building struct, enum, trait and impl
The source code is available in the [`examples`](https://github.com/mtshiba/ruast/tree/main/examples) directory.
```rust
use ruast::*;let mut krate = Crate::new();
let def = StructDef::empty("Foo")
.with_field(FieldDef::inherited("foo", Type::from("u32")))
.with_field(FieldDef::inherited("bar", Type::from("u32")));
krate.add_item(def);
let imp = Impl::empty("Foo")
.with_item(Fn::empty_method("test", Pat::ref_self()));
krate.add_item(imp);
println!("{krate}");
``````rust
use ruast::*;let mut krate = Crate::new();
let def = EnumDef::empty("Foo")
.with_variant(Variant::empty("Bar"))
.with_variant(Variant::tuple("Baz", vec![FieldDef::anonymous("u32")]));
krate.add_item(def);
let imp = Impl::empty("Foo")
.with_item(Fn::empty_method("test", Pat::ref_self()));
krate.add_item(imp);
println!("{krate}");
``````rust
use ruast::*;let mut krate = Crate::new();
let partial_eq = Type::simple_path("PartialEq");
let trait_def = TraitDef::new("Eq", vec![], vec![partial_eq], vec![]);
krate.add_item(trait_def);
let arg_t = GenericArg::Type(Type::simple_path("T"));
let eq_bound = GenericBound::Trait(PolyTraitRef::simple("Eq"));
let eq = Type::simple_path("Eq");
let param_t = GenericParam::new("T", vec![eq_bound]);
let self_ty = Type::poly_path("Vec", vec![arg_t]);
let imp = Impl::trait_impl(vec![param_t], self_ty, eq, None, vec![]);
krate.add_item(imp);
println!("{krate}");
```### Convert to `proc_macro2::TokenStream`
By enabling a feature `tokenize`, you can convert `ruast` ASTs to `proc_macro2::TokenStream`.
You can build ASTs systematically without using `syn` or `quote` macros.
```rust
use ruast::*;let mut krate = Crate::new();
let def = Fn::main(
None,
Block::from(Path::single("println").mac_call(vec![Token::lit("Hello, world!")])),
);
krate.add_item(def);
let tokens = krate.to_token_stream();
println!("{krate}");
println!("{tokens}");
```## Why this is needed?
[The Rust project](https://github.com/rust-lang/rust) has a submodule called [`rustc_ast`](https://github.com/rust-lang/rust/tree/master/compiler/rustc_ast) that defines an AST, but it is not published on crates.io and requires a huge build of `rust` itself. Also, `rustc_ast` is not designed for third parties to build ASTs by hand.
There is a [`codegen`](https://github.com/carllerche/codegen) crate for Rust code generation, but this crate has not been maintained for some time and only supports basic syntax elements.
There is also a [`syn`](https://github.com/dtolnay/syn) crate that can parse `proc_macro::TokenStream` into an AST, but its AST elements don't implement `Display` trait and are not designed for direct construction & modification.
## Goals
The goal of this project is to provide a simple and portable Rust AST building/Rust code generation library.
## Non-goals
This library is not directly related to the Rust compiler AST, and ASTs built with this library cannot be directly given as input to the compiler.
## License
This project is licensed under either of [Apache license version 2.0](./LICENSE-APACHE) or [MIT license](./LICENSE-MIT) at your option.