Rust crate for outputting Rust code?

I've used procedural macros before. I'm looking for something different.

I'm currently writing a Rust program which outputs a file (that contains Rust code). Right now, it is a BufWriter, a bunch of write! calls. I'm wondering if there is a crate aimed at this task.

Thanks!

quote sounds like it could be useful to you.

2 Likes

syn and quote are generally used in proc macros, but they can be used to generate files too. As quote mentions, you'll probably want to put the output through prettyplease too though.

TBH, though, I have just used write!() myself, not doing anything all that complex.

3 Likes

I've done a fair amount of code generation in Rust and generally all you need is the proc-macro2 crate and quote. I prefer quote!() over a bare write!() because it lets you take a step away from the nuts and bolts of string interpolation and closer to generating Rust code.

If you want to have nicely formatted code, the prettyplease crate is quite handy because it decouples you from rustfmt, which may not always be installed or could change its formatting style from version-to-version and trigger unnecessary "the generated code needs updating" issues.

Other than those crates, this is all the extra boilerplate I'll need:

Once I've got that in place, I normally stick the code generation into a test which uses ensure_file_contents() to make sure the generated code is up to date.

4 Likes
  1. You have convinced me to use quote! over write!

  2. I don't see this in the two examples you linked above, after

let tokens = quote! { ... }

is there an easy way to dump tokens to file / convert it to string ?

The proc_macro2::TokenStream type implements Display, so you can always call to_string() on it or write!() the tokens to a file.

The bit doing the formatting and stringifying was just above ensure_file_contents().

The actual code that uses quote!() is pretty complex because I'm taking an *.ungrammar file and turning it into a series of token types (code/generated) and strongly-typed AST nodes (code/generated). It was mostly copied from another, much more complex parser and language server I wrote, but the code for that isn't open-source yet.

The original inspiration came from @matklad's amazing video walkthrough of Rust Analyzer on YouTube and the Self Modifying Code article he wrote.

1 Like

Its amazing how pleasant quoting / unquoting can be when used OUTSIDE procedural macros :slight_smile:

If the goal is to compute data and write it as literals, then check out uneval.