use proc_macro::{Delimiter, Group, Ident, Literal, Span, TokenStream, TokenTree};
use super::{
eval::Eval,
util::{must_be_assign, must_be_comma, next_token},
};
pub(crate) fn run(value_mode: ValueMode, input: TokenStream) -> TokenStream {
let mut iter = input.into_iter();
let mut v = Vec::<TokenTree>::new();
let mut tt = next_token(&mut iter);
let tag_name = match tt {
proc_macro::TokenTree::Ident(i) => {
if i.to_string() == "tag" {
tt = next_token(&mut iter);
must_be_assign(&tt);
tt = next_token(&mut iter);
let tag_name = match tt {
TokenTree::Ident(i) => i.to_string(),
_ => panic!("Expected identifier with tag name"),
};
tt = next_token(&mut iter);
must_be_comma(&tt);
tag_name
} else {
let backup = Ident::new(&i.to_string(), i.span());
v.push(TokenTree::Ident(backup));
"default".to_owned()
}
}
_ => {
v.push(tt);
"default".to_owned()
}
};
loop {
match iter.next() {
Some(tt) => v.push(tt),
None => break,
}
}
let group = Group::new(Delimiter::Parenthesis, v.into_iter().collect());
let eval = Eval::new_tagged(&tag_name, &group).eval();
let tt = match value_mode {
ValueMode::Int => match eval.as_int() {
Some(i) => TokenTree::Literal(Literal::i64_suffixed(i)),
None => panic!("Configured value is not an integer"),
},
ValueMode::String => {
let s = eval.as_string();
TokenTree::Literal(Literal::string(&s))
}
ValueMode::Bool => {
let bool = match eval.as_bool() {
true => "true",
false => "false",
};
TokenTree::Ident(Ident::new(bool, Span::call_site()))
}
};
vec![tt].into_iter().collect()
}
pub(crate) enum ValueMode {
Int,
String,
Bool,
}