use crate::parsing::c::lex::tokens::{TOK_HASH, TOK_HASHHASH};
use vyre_foundation::ir::{Expr, Node};
use super::arg_scan::emit_function_like_argument_scan;
pub(super) struct FunctionLikeReplacementSpec<'a> {
pub(super) in_tok_types: &'a str,
pub(super) macro_vals: &'a str,
pub(super) macro_replacement_params: &'a str,
pub(super) macro_arg_starts: &'a str,
pub(super) macro_arg_ends: &'a str,
pub(super) num_tokens: Expr,
pub(super) stringify: Vec<Node>,
pub(super) paste: Vec<Node>,
pub(super) regular: Vec<Node>,
}
pub(super) fn emit_function_like_replacement_walk(
spec: FunctionLikeReplacementSpec<'_>,
) -> Vec<Node> {
let mut nodes = emit_function_like_argument_scan(
spec.in_tok_types,
spec.macro_arg_starts,
spec.macro_arg_ends,
spec.num_tokens,
);
nodes.extend([
Node::let_bind("named_skip_repl", Expr::u32(0)),
Node::loop_for(
"named_repl_i",
Expr::u32(0),
Expr::var("named_repl_size"),
vec![Node::if_then_else(
Expr::eq(Expr::var("named_skip_repl"), Expr::u32(1)),
vec![Node::assign("named_skip_repl", Expr::u32(0))],
{
let mut repl = vec![
Node::let_bind(
"named_repl_offset",
Expr::add(Expr::var("named_macro_idx"), Expr::var("named_repl_i")),
),
Node::let_bind(
"named_repl_param",
Expr::load(
spec.macro_replacement_params,
Expr::var("named_repl_offset"),
),
),
Node::let_bind(
"named_repl_tok",
Expr::load(spec.macro_vals, Expr::var("named_repl_offset")),
),
];
repl.push(Node::if_then_else(
Expr::and(
Expr::eq(Expr::var("named_repl_tok"), Expr::u32(TOK_HASH)),
Expr::lt(
Expr::add(Expr::var("named_repl_i"), Expr::u32(1)),
Expr::var("named_repl_size"),
),
),
spec.stringify,
vec![Node::if_then_else(
Expr::eq(Expr::var("named_repl_tok"), Expr::u32(TOK_HASHHASH)),
spec.paste,
spec.regular,
)],
));
repl
},
)],
),
Node::assign(
"named_i",
Expr::add(Expr::var("macro_close_idx"), Expr::u32(1)),
),
]);
nodes
}