Polyquine: Teach Rust types to codegen their own constructor!
crates.io: polyquine
cargo add polyquine
Purpose
This crate contains:
- A
Quinetrait. Types that implementQuinehave a methodctor_tokens(&self) -> TokenStream; The tokens returned by it are valid Rust expression that, when evaluated, produces the original value. - Implementations for:
- All primitives (
i32,bool, etc.) String- Fixed-size arrays
[T; N] - Some
std::collectionstypes (Vec,HashMap,HashSet, etc.) - Tuples of up to 12 elements
Box<T>,Option<T>
- All primitives (
- Declarative macros to implement
Quinefor:- Iterables (
derive_iterable). The given iterable must:- Have an
.iter()method that returns an iterator over its elements. - Implement
From<[T; N]>
- Have an
- Iterables (
- A
#[derive(Quine)]macro to derive the trait for enums and structs. All fields thereof must implementQuine.
For example:
let node = Node ;
assert_ts_eq;
Notes
- Version
0.0.2is a complete rewrite. We now use our own trait instead of derivingquote::ToTokens. All field attributes from version0.0.1are no longer supported. - We ignore references, i.e. the implementation for
&Tis the same as forT. This may cause issues - please open an issue if you encounter any. - Please open an issue if any
stdtype is not supported and you need it. Rc,Arcand friends are unlikely to ever be supported. This is due to their shared ownership semantics: We can have multipleRc's pointing to the same memory. When implementingQuine, the best we can do is re-construct their values separately. When evaluated, we will now have multiple independent copies of the original value - not a single value behind a shared reference.
Acknowledgements
Partially inspired by the parsel crate.
Why?
This is intended for cases where you need to construct a value and do some non-trivial logic on it at compile time (probably in a procedural macro), then take the result out of the macro as valid Rust code.
For example, when you are parsing a DSL at compile time and outputting the constructed (and possibly simplified / transformed) AST as the result of your macro call.
See this PR as proof that this use case is not completely made up.
TODO
- More testing
- Skipping or overriding implementation for fields.
Production readiness
still no.
Why the name?
A quine is a program that outputs its own source code. This crate teaches an arbitrary enum / struct to generate a Rust program that constructs it, thereby making it a quine. So, polyquine! This is only slightly pretentious.
also, trans rights! 🏳️⚧️