use cairo_lang_semantic::test_utils::setup_test_function;
use cairo_lang_test_utils::parse_test_file::TestRunnerResult;
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use crate::db::LoweringGroup;
use crate::ids::ConcreteFunctionWithBodyId;
use crate::optimizations::strategy::{ApplyOptimization, OptimizationPhase};
use crate::test_utils::{LoweringDatabaseForTesting, formatted_lowered};
use crate::{Lowered, LoweringStage};
pub fn run_lowering_phases_test<'db>(
inputs: &OrderedHashMap<String, String>,
stage: LoweringStage,
before_phases: &[OptimizationPhase<'db>],
after_phases: &[OptimizationPhase<'db>],
) -> TestRunnerResult {
run_lowering_phases_test_with_db(
LoweringDatabaseForTesting::default(),
inputs,
stage,
before_phases,
after_phases,
)
}
pub fn run_lowering_phases_test_with_db<'db>(
db: LoweringDatabaseForTesting,
inputs: &OrderedHashMap<String, String>,
stage: LoweringStage,
before_phases: &[OptimizationPhase<'db>],
after_phases: &[OptimizationPhase<'db>],
) -> TestRunnerResult {
run_test(db, inputs, stage, before_phases, after_phases, |_, _| vec![])
}
pub fn run_lowering_phases_test_with_extra_outputs<'db>(
inputs: &OrderedHashMap<String, String>,
stage: LoweringStage,
before_phases: &[OptimizationPhase<'db>],
after_phases: &[OptimizationPhase<'db>],
extra_outputs: impl FnOnce(&Lowered<'_>, &Lowered<'_>) -> Vec<(String, String)>,
) -> TestRunnerResult {
run_test(
LoweringDatabaseForTesting::default(),
inputs,
stage,
before_phases,
after_phases,
extra_outputs,
)
}
fn run_test<'db>(
mut db: LoweringDatabaseForTesting,
inputs: &OrderedHashMap<String, String>,
stage: LoweringStage,
before_phases: &[OptimizationPhase<'db>],
after_phases: &[OptimizationPhase<'db>],
extra_outputs: impl FnOnce(&Lowered<'_>, &Lowered<'_>) -> Vec<(String, String)>,
) -> TestRunnerResult {
let db = &mut db;
let (test_function, semantic_diagnostics) = setup_test_function(db, inputs).split();
if !semantic_diagnostics.is_empty() {
return TestRunnerResult::success(OrderedHashMap::from([(
"semantic_diagnostics".into(),
semantic_diagnostics,
)]));
}
let function_id =
ConcreteFunctionWithBodyId::from_semantic(db, test_function.concrete_function_id);
let lowering_diagnostics = db.module_lowering_diagnostics(test_function.module_id).unwrap();
let (before, after) = match db.lowered_body(function_id, stage) {
Ok(lowered) => {
let mut before = lowered.clone();
before_phases.apply(db, function_id, &mut before).unwrap();
let mut after = before.clone();
after_phases.apply(db, function_id, &mut after).unwrap();
(Some(before), Some(after))
}
Err(_) => (None, None),
};
let mut outputs = OrderedHashMap::from([
("semantic_diagnostics".into(), semantic_diagnostics),
("before".into(), formatted_lowered(db, before.as_ref())),
("after".into(), formatted_lowered(db, after.as_ref())),
("lowering_diagnostics".into(), lowering_diagnostics.format(db)),
]);
if let (Some(before), Some(after)) = (&before, &after) {
outputs.extend(extra_outputs(before, after));
}
TestRunnerResult::success(outputs)
}