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}