use crate::*;
use leo_ast::NetworkName;
use leo_errors::{BufferEmitter, Handler};
use leo_parser::parse_ast;
use leo_span::{create_session_if_not_set_then, source_map::FileName, with_session_globals};
use serial_test::serial;
macro_rules! compiler_passes {
($macro:ident) => {
$macro! {
(common_subexpression_elimination_runner, CommonSubexpressionEliminating, (), true),
(const_prop_unroll_and_morphing_runner, ConstPropUnrollAndMorphing, (TypeCheckingInput::new(NetworkName::TestnetV0)), true),
(destructuring_runner, Destructuring, (), true),
(dead_code_elimination_runner, DeadCodeEliminating, (), true),
(flattening_runner, Flattening, (), true),
(function_inlining_runner, FunctionInlining, (), true),
(option_lowering_runner, OptionLowering, (TypeCheckingInput::new(NetworkName::TestnetV0)), true),
(processing_async_runner, ProcessingAsync, (TypeCheckingInput::new(NetworkName::TestnetV0)), true),
(processing_script_runner, ProcessingScript, (), true),
(ssa_forming_runner, SsaForming, (SsaFormingInput { rename_defs: true }), true),
(storage_lowering_runner, StorageLowering, (TypeCheckingInput::new(NetworkName::TestnetV0)), true),
(write_transforming_runner, WriteTransforming, (), true),
(remove_unreachable, RemoveUnreachable, (), false)
}
};
}
macro_rules! make_runner {
($runner_name:ident, $pass:ident, $input:expr, $run_prelude:expr) => {
fn $runner_name(source: &str) -> String {
let buf = BufferEmitter::new();
let handler = Handler::new(buf.clone());
create_session_if_not_set_then(|_| {
let mut state = CompilerState { handler: handler.clone(), ..Default::default() };
state.ast = match handler.extend_if_error(parse_ast(
handler.clone(),
&state.node_builder,
&with_session_globals(|s| s.source_map.new_source(source, FileName::Custom("test".into()))),
&[],
NetworkName::TestnetV0,
)) {
Ok(ast) => ast,
Err(()) => return format!("{}{}", buf.extract_errs(), buf.extract_warnings()),
};
if $run_prelude {
if handler.extend_if_error(PathResolution::do_pass((), &mut state)).is_err() {
return format!("{}{}", buf.extract_errs(), buf.extract_warnings());
}
if handler.extend_if_error(SymbolTableCreation::do_pass((), &mut state)).is_err() {
return format!("{}{}", buf.extract_errs(), buf.extract_warnings());
}
if handler
.extend_if_error(TypeChecking::do_pass(TypeCheckingInput::new(state.network), &mut state))
.is_err()
{
return format!("{}{}", buf.extract_errs(), buf.extract_warnings());
}
}
if handler.extend_if_error($pass::do_pass($input, &mut state)).is_err() {
return format!("{}{}", buf.extract_errs(), buf.extract_warnings());
}
format!("{}{}", buf.extract_warnings(), state.ast.ast)
})
}
};
}
macro_rules! make_all_runners {
($(($runner:ident, $pass:ident, $input:tt, $run_prelude:tt)),* $(,)?) => {
$(
make_runner!($runner, $pass, $input, $run_prelude);
)*
};
}
compiler_passes!(make_all_runners);
macro_rules! make_all_tests {
($(($runner:ident, $pass:ident, $input:tt, $run_prelude:tt)),* $(,)?) => {
$(
paste::paste! {
#[test]
#[serial]
fn [<$runner _test>]() {
leo_test_framework::run_tests(
concat!("passes/", stringify!([<$pass:snake>])),
$runner,
);
}
}
)*
};
}
compiler_passes!(make_all_tests);