1use airl_ir::ids::{FuncId, TypeId};
4use airl_ir::module::Module;
5use serde::{Deserialize, Serialize};
6
7use crate::ops::PatchOp;
8use crate::traverse;
9
10#[derive(Clone, Debug, Default, Serialize, Deserialize)]
12pub struct Impact {
13 pub affected_functions: Vec<FuncId>,
15 pub affected_types: Vec<TypeId>,
17}
18
19pub fn analyze_impact(module: &Module, ops: &[PatchOp]) -> Impact {
21 let mut affected_functions = Vec::new();
22 let affected_types = Vec::new();
23
24 for op in ops {
25 match op {
26 PatchOp::ReplaceNode { target, .. } => {
27 let funcs = traverse::functions_containing_node(module, target);
28 for f in funcs {
29 if !affected_functions.contains(&f) {
30 affected_functions.push(f);
31 }
32 }
33 }
34 PatchOp::AddFunction { func } => {
35 if !affected_functions.contains(&func.id) {
36 affected_functions.push(func.id.clone());
37 }
38 }
39 PatchOp::RemoveFunction { func_id } => {
40 if !affected_functions.contains(func_id) {
41 affected_functions.push(func_id.clone());
42 }
43 }
44 PatchOp::RenameSymbol { scope, .. } => {
45 if let Some(func_id) = scope {
46 if !affected_functions.contains(func_id) {
47 affected_functions.push(func_id.clone());
48 }
49 } else {
50 for func in module.functions() {
52 if !affected_functions.contains(&func.id) {
53 affected_functions.push(func.id.clone());
54 }
55 }
56 }
57 }
58 PatchOp::AddEffect { func_id, .. } | PatchOp::RemoveEffect { func_id, .. } => {
59 if !affected_functions.contains(func_id) {
60 affected_functions.push(func_id.clone());
61 }
62 }
63 PatchOp::AddImport { .. } | PatchOp::RemoveImport { .. } => {
64 }
67 }
68 }
69
70 Impact {
71 affected_functions,
72 affected_types,
73 }
74}