1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//! Use-site metaprogramming inspired by staging
//!
//! This crate lets you run code at compile time to produce the tokens other proc_macros will consume.
//! It is also useful for ad-hoc in place code generation, and for making templates (like Jinja or Mustache for your code).
//! It uses its own simple inner language based on handlers, variables, and a user chosen sigil.
//! The stage separation model of Rust does impose some limitations on what this crate can do.
//!
//! There are two common ways to use this crate. As an end user, it is most likely that you will use the [do_with_in] proc_macro directly.
//! But if you want to make use of parts of the functionality in order to implement these features into your own proc_macro directly,
//! or to implement your own handlers offering extended functionality in the staged language, you'll end up (at this stage) using the reexports from
//! [do_with_in_base], most notably [do_with_in_explicit2].
//!
//! The base handler list is in [genericDefaultHandlers].

extern crate proc_macro;
extern crate syn;
#[macro_use] extern crate quote;
extern crate proc_macro2;

use proc_macro::{TokenStream, TokenTree};
use proc_macro2::TokenTree as TokenTree2;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use quote::ToTokens;
use syn::{parse, Attribute, PathSegment, Result, Token};
use syn::parse::{Parse, ParseStream, Parser, Peek};
use syn::spanned::Spanned;
use syn::{Expr, Ident, Type, Visibility};
use syn::punctuated::Punctuated;
use syn::parenthesized;
use syn::token::Token;
use syn::buffer::Cursor;

use std::marker::PhantomData;

use std::collections::HashMap;
use std::fmt::format;

/// The function used to actually run a stage.
///
/// The tokens in `t` are run, using sigils and so on specified in `c` and variables and handlers specified in `v`.
/// This can be used directly inside a proc_macro to give it the features of [do_with_in]; that proc_macro is in fact
/// essentially a thin wrapper around [do_with_in_internal], which is a configuration parsing wrapper around this function. If you are
/// using it this way, you can also change the default variables and handlers which are available by passing in your own `v`.
/// [genericDefaultHandlers] gives a list of the default handlers, and the source of that function shows how to create the handlers;
/// [Variables] implements `Default`, so you can easily get a 'batteries included' version to extend.
#[doc(inline)]
pub use do_with_in_base::do_with_in_explicit2;

#[doc(inline)]
pub use do_with_in_base::*;


/// This is the proc_macro most users of this crate will use.
///
/// There is front matter, which can define the sigil and escaping style. Escaping doesn't actually do anything yet though.
/// Then `do`, then after that is where the metaprogramming can happen.
///
/// In the metaprogramming section, variables are identifiers with a sigil prepended. You can create and assign to them with `let` and `var` handlers.
/// Numbers with a sigil prepended are special variables that can be set inside a handler; you cannot assign to them with `let` or `var`.
/// Brackets with a sigil prepended start a handler invocation; the handler invoked will be the first token inside the brackets, which must be an identifier.
///
/// For example, in the following code the sigil is `$`, `$correction_factor` is a normal variable, `$1`, `$2`, and `$3` are special variables set inside the `blah` handler,
/// and `$(let ...)`, `$(mk ...)` and `$(blah ...)` are all handlers.
///
/// ```rust
/// # use do_with_in_internal_macros::do_with_in;
/// # fn main() {
/// do_with_in!{
///    sigil: $
///    do
///    $(let correction_factor = {(-1)})
///    $(mk blah
///        $1 = $2 + $3 + $correction_factor;)
///    $(blah {let mut d} 3 4)
///    d += 1;
///    let correction_factor = $correction_factor;
///  };
///  assert_eq!(d, 8 + correction_factor);
/// # }
/// ```
///
/// For a table of the currently useful handlers that are available by default, see [genericDefaultHandlers].
#[doc(inline)]
pub use do_with_in_internal_macros::do_with_in;