wagon_codegen/
lib.rs

1#![warn(missing_docs)]
2//! Generally useful methods to convert a WAG to Rust code.
3//!
4//! A WAG may be converted into code in any number of ways for any number of reasons. This crate intends to hold
5//! code that is generally useful, regardless of the purpose of the final generated code.
6
7/// Codegen for parts of the [`wagon-parser`] AST that are generally useful.
8pub mod nodes;
9/// A datastructure that represents a structure and data to write to disk.
10mod filestructure;
11
12use std::rc::Rc;
13use proc_macro2::{TokenStream, Ident};
14use wagon_parser::{parser::Parse, SpannableNode};
15pub use filestructure::{FileStructure, FileType};
16
17/// A quick type alias to represent a [`wagon_ident::Ident`] with span information.
18pub type SpannableIdent = SpannableNode<wagon_ident::Ident>;
19
20/// A trait for anything that does codegen while having to keep track of some state object `U`.
21pub trait ToTokensState<U> {
22    /// A method to do codegen based on state and possibly modify that state.
23    ///
24    /// This method takes a given mutable state `U`, as well as a reference to some [`proc_macro2::Ident`] and a function to modify the state.
25    /// It then potentially calls this function to modify the state and returns a `TokenStream` for the generated code.
26    ///
27    /// # Example
28    /// ```
29    /// # use wagon_parser::SpannableNode;
30    /// # use proc_macro2::TokenStream;
31    /// # use wagon_codegen::{SpannableIdent, ToTokensState};
32    /// # use std::rc::Rc;
33    /// struct A;
34    /// struct State { toggle: bool }
35    /// impl State {
36    ///     fn new() -> Self {
37    ///         Self { toggle: false }  
38    ///     }
39    ///     fn toggle(&mut self, _: Rc<proc_macro2::Ident>, _: SpannableIdent) {
40    ///         self.toggle = true;
41    ///     }   
42    /// }
43    /// impl ToTokensState<State> for A {
44    ///     fn to_tokens(&self, state: &mut State, label: Rc<proc_macro2::Ident>, attr_fun: fn(&mut State, Rc<proc_macro2::Ident>, SpannableIdent)) -> TokenStream {
45    ///         attr_fun(state, label, SpannableNode::from(wagon_ident::Ident::default()));
46    ///         TokenStream::new()
47    ///     }
48    /// }
49    /// let a = A;
50    /// let mut state = State { toggle: false };
51    /// let label = Rc::new(proc_macro2::Ident::new("label", proc_macro2::Span::call_site()));
52    /// a.to_tokens(&mut state, label, State::toggle);
53    /// assert!(state.toggle) // this is now true
54    /// ```
55    ///
56    /// For practical examples. Look at the implementations in this crate as well as how they are called in the [`wagon-codegen-gll`] crate.
57	fn to_tokens(&self, state: &mut U, label: Rc<Ident>, attr_fun: fn(&mut U, Rc<Ident>, SpannableIdent)) -> TokenStream;
58}
59
60impl<U, T: Parse + ToTokensState<U>> ToTokensState<U> for SpannableNode<T> {
61    fn to_tokens(&self, state: &mut U, label: Rc<Ident>, attr_fun: fn(&mut U, Rc<Ident>, SpannableIdent)) -> TokenStream {
62        self.to_inner().to_tokens(state, label, attr_fun)
63    }
64}