aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_macros/src/mbe_expander.rs
blob: f55c337da6f670a950d163472e1417762c9da87b (plain)
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
use rustc_hash::FxHashMap;
use smol_str::SmolStr;

use crate::{mbe, tt};

pub fn exapnd(rules: &mbe::MacroRules, input: &tt::Subtree) -> Option<tt::Subtree> {
    rules.rules.iter().find_map(|it| expand_rule(it, input))
}

fn expand_rule(rule: &mbe::Rule, input: &tt::Subtree) -> Option<tt::Subtree> {
    let bindings = match_lhs(&rule.lhs, input)?;
    expand_rhs(&rule.rhs, &bindings)
}

#[derive(Debug, Default)]
struct Bindings {
    inner: FxHashMap<SmolStr, Binding>,
}

#[derive(Debug)]
enum Binding {
    Simple(tt::TokenTree),
    Nested(Vec<Binding>),
}

/*

macro_rules! impl_froms {
    ($e:ident: $($v:ident),*) => {
        $(
            impl From<$v> for $e {
                fn from(it: $v) -> $e {
                    $e::$v(it)
                }
            }
        )*
    }
}

impl_froms! (Foo: Bar, Baz)

*/

fn match_lhs(pattern: &mbe::Subtree, input: &tt::Subtree) -> Option<Bindings> {
    let mut res = Bindings::default();
    for pat in pattern.token_trees.iter() {
        match pat {
            mbe::TokenTree::Leaf(leaf) => match leaf {
                mbe::Leaf::Var(mbe::Var { text, kind }) => {
                    let kind = kind.clone()?;
                    match kind.as_str() {
                        "ident" => (),
                        _ => return None,
                    }
                }
                _ => return None,
            },
            _ => {}
        }
    }
    Some(res)
}

fn expand_rhs(template: &mbe::Subtree, bindings: &Bindings) -> Option<tt::Subtree> {
    None
}