use crate::parsing::c::lex::tokens::TOK_HASHHASH;
use crate::parsing::c::preprocess::synthesis::*;
use vyre_foundation::ir::{Expr, Node};
use super::*;
pub(super) fn emit_object_like_token_paste_prefix(
macro_vals: &str,
macro_replacement_params: &str,
out_tok_types: &str,
synth_failure_trap: &'static str,
) -> Vec<Node> {
vec![
Node::if_then(
Expr::eq(Expr::var("named_out_idx"), Expr::u32(0)),
vec![Node::trap(
Expr::var("named_repl_i"),
"object-like-token-paste-missing-left-token",
)],
),
Node::if_then(
Expr::ge(
Expr::add(Expr::var("named_repl_i"), Expr::u32(1)),
Expr::var("named_repl_size"),
),
vec![Node::trap(
Expr::var("named_repl_i"),
"object-like-token-paste-missing-right-token",
)],
),
Node::let_bind(
"macro_paste_next_offset",
Expr::add(
Expr::var("named_macro_idx"),
Expr::add(Expr::var("named_repl_i"), Expr::u32(1)),
),
),
Node::let_bind(
"macro_paste_next_param",
Expr::load(
macro_replacement_params,
Expr::var("macro_paste_next_offset"),
),
),
Node::if_then(
Expr::ne(
Expr::var("macro_paste_next_param"),
Expr::u32(C_MACRO_REPLACEMENT_LITERAL),
),
vec![Node::trap(
Expr::var("macro_paste_next_param"),
"object-like-token-paste-cannot-reference-parameters",
)],
),
Node::let_bind(
"macro_paste_left_tok",
Expr::load(
out_tok_types,
Expr::sub(Expr::var("named_out_idx"), Expr::u32(1)),
),
),
Node::let_bind(
"macro_paste_right_tok",
Expr::load(macro_vals, Expr::var("macro_paste_next_offset")),
),
Node::let_bind(
"macro_paste_synth_tok",
synthesized_paste_token(
Expr::var("macro_paste_left_tok"),
Expr::var("macro_paste_right_tok"),
),
),
Node::if_then(
Expr::eq(
Expr::var("macro_paste_synth_tok"),
Expr::u32(EMPTY_MACRO_SLOT),
),
vec![Node::trap(
Expr::var("macro_paste_right_tok"),
synth_failure_trap,
)],
),
Node::store(
out_tok_types,
Expr::sub(Expr::var("named_out_idx"), Expr::u32(1)),
Expr::var("macro_paste_synth_tok"),
),
]
}
pub(super) fn emit_object_like_replacement_loop(
macro_vals: &str,
macro_replacement_params: &str,
paste_branch: Vec<Node>,
literal_branch: Vec<Node>,
) -> Vec<Node> {
vec![
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 body = 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(macro_replacement_params, Expr::var("named_repl_offset")),
),
Node::if_then(
Expr::ne(
Expr::var("named_repl_param"),
Expr::u32(C_MACRO_REPLACEMENT_LITERAL),
),
vec![Node::trap(
Expr::var("named_repl_param"),
"object-like-macro-replacement-cannot-reference-parameters",
)],
),
Node::let_bind(
"named_repl_tok",
Expr::load(macro_vals, Expr::var("named_repl_offset")),
),
];
body.push(Node::if_then_else(
Expr::eq(Expr::var("named_repl_tok"), Expr::u32(TOK_HASHHASH)),
paste_branch,
literal_branch,
));
body
},
)],
),
Node::assign("named_i", Expr::add(Expr::var("named_i"), Expr::u32(1))),
]
}
pub(super) fn synthesized_paste_token(left: Expr, right: Expr) -> Expr {
C_TOKEN_PASTE_RULES.iter().rev().fold(
Expr::u32(EMPTY_MACRO_SLOT),
|fallback, (left_tok, right_tok, out_tok)| {
Expr::select(
Expr::and(
Expr::eq(left.clone(), Expr::u32(*left_tok)),
Expr::eq(right.clone(), Expr::u32(*right_tok)),
),
Expr::u32(*out_tok),
fallback,
)
},
)
}