Git Product home page Git Product logo

proc-macro-template's Introduction

proc-macro-template

This repo contains cargo-generate templates intended to simplify developing procedural macros in the style described by the ferrous systems blog post on testing proc macros.

To quickly summarize the approach recommended there and which is adhered to by these templates, procedural macro expansion is broken down into four distinct stages:

parse
Parse the contents of the input [TokenStream](https://doc.rust-lang.org/proc_macro/struct.TokenStream.html) to produce an Abstract Syntax Tree (AST) in Rust that represents the structure of the macro. The AST is likely to consist of structs and enums whose contents are [syn](https://docs.rs/syn) token types (at least, that's the assumption made by the templates in this repo).
analyze
Transform the AST of the macro into a Rust model abstracting over the domain of the macro.
lower
Transform the model into an "intermediate representation" (IR) of the output code generated by the macro. This IR, similar to the AST, should probably consist mostly if not entirely of [syn](https://docs.rs/syn) tokens, which simplifies the process of producing a [TokenStream](https://doc.rust-lang.org/proc_macro/struct.TokenStream.html) in the final stage, `codegen`
codegen
Transform the IR into a [TokenStream](https://doc.rust-lang.org/proc_macro/struct.TokenStream.html) using the [quote!](https://docs.rs/quote/latest/quote/macro.quote.html) macro.

If you're wondering "why does it need to be broken down like this?", then you should probably read the abovementioned blog post about testing procedural macros. But the answer to your question is, "it doesn't".

A quick note about crates used

So far in my time learning about procedural macros, I have come across a small ecosystem of crates all written by the same author:

  • proc_macro2
  • proc_macro_error
  • syn
  • quote

There are probably more, but I want to point them out here because I understand it can be mildly confusing and to get started writing procedural macros and I'd like to help whatever poor soul finds their self resting their weary eyes on these bedraggled words.

proc_macro2

proc_macro2 is an abstraction over the upstream Rust proc_macro library that, for the purpose of these templates, serves to enable unit testing of procedural macro helper code. This is not possible with the upstream proc_macro types because they can only ever be used directly inside a procedural macro.

It's worth noting that proc_macro2 and proc_macro both export a type called TokenStream. proc_macro2::TokenStream, in my very limited understanding, is necessary since the upstream proc_macro::TokenStream type can only be used in the definition of actual procedural macro functions (ie not helper functions or unit tests).

proc_macro_error

proc_macro_error claims to make procedural macro error reporting simple and easy to use. I did have some difficulty with it myself initially when I was working on my first macro parser, but I've also never tried any alternative so I take the author at their word. I can definitely attest that the error messages I've seen while using it were mildly useful, though I did also find myself making liberal use of eprintln! since the syntax I was parsing is very custom and DSL-like.

syn

syn is arguably the powerhouse of this collection of procedural macro crates and the one you will undoubtedly spend the most time with if the syntax you are parsing or code you are generating involves any non-trivial amount of complexity. It contains various types representing valid Rust tokens and parsing functions and traits that simplify your life as a macro writer. It's definitely worth reading the code to understand:

  • the Parser trait
  • the various parse functions
  • and other stuff I'm probably forgetting right now

quote

quote is a crate that exports a macro of the same name that will expand the "example" rust syntax passed to it using in-scope variables to produce a proc_macro2::TokenStream instance that can be converted into proc_macro::TokenStream and returned as the output of the procedural macro.

proc-macro-template's People

Contributors

waynr avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.