Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
uniplate_derive: add new Uniplate derive macro
Reimplement the uniplate-derive macro to allow for Biplates and "multiple type traversals" as discussed in [Niklas Dewally, 2024‐03: Implementing Uniplates and Biplates with Structure Preserving Trees]. (currently at https://github.com/conjure-cp/conjure-oxide/wiki/2024%E2%80%9003-Implementing-Uniplates-and-Biplates-with-Structure-Preserving-Trees). Implementation overview ======================= The library syn supports the creation of custom AST nodes. Using the Parse trait, one can implement parsers for these custom nodes by combining existing Rust AST nodes together as well as parsing Rust tokens by hand. The macro code has two parts: parsing into a custom AST, and using this AST for code-gen. This simplifies code-gen, as only the data needed for Uniplate is encoded in the AST. This also allows for better error reporting, as Most errors are now reported during parsing, allowing errors to be associated with the specific tokens that caused them. The biggest change in Uniplate's AST compared to Rust's is the representation of types. Uniplate has three kinds of type: boxed pointer types, plateable types, and unpalatable types. Plateable types include the current type being derived, or other types explicitly specified through the walk_through attribute in the macro invocation. Boxed pointer types represent smart pointers such as Box and Rc. These use the .borrow() function instead of & to pass the inner value to the Biplate instance. Generating instances for Box<A> and Rc<A> would mean that values are constantly moved from stack to heap - this avoids this. Implementations for standard library iterator types and primitives are provided by Uniplate. These implementations are generated by declarative macro, allowing easy extension to more collection types in the future. Testing ======= Add trybuild, a library for UI testing derive macros. The Rust tester does not run at-all when test code does not compile, but we need to test whether our macro gives a compile error when it should. trybuild also checks that the error messages given by the compiler have not changed. Two test ASTs are used for Uniplate and Biplates: a toy statement-expression found in the original paper, and the current Conjure Oxide AST. Property-based testing in paper.rs shows that children() and with_children() work for random homogenous AST's, including with boxes and iterators. As these two methods essentially act as wrappers for the child tree and context function returned by the uniplate() / biplate() methods, this test is sufficient to show that automatically derived Uniplate implementations act as intended. Signed-off-by: Niklas Dewally <niklas@dewally.com>
- Loading branch information