# `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 hello
fn 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.