pub struct SymbolicExecutor {
loop_depths: Vec<Complexity>,
recursive_depth: usize,
function_complexities: HashMap<String, Complexity>,
current_path_complexity: Complexity,
}
impl Default for SymbolicExecutor {
fn default() -> Self {
Self::new()
}
}
impl SymbolicExecutor {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn new() -> Self {
Self {
loop_depths: Vec::new(),
recursive_depth: 0,
function_complexities: HashMap::new(),
current_path_complexity: Complexity::O1,
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn analyze_function(&mut self, func: &syn::ItemFn) -> Complexity {
let name = func.sig.ident.to_string();
self.loop_depths.clear();
self.current_path_complexity = Complexity::O1;
let mut recursion_detector = RecursionDetector {
function_name: name.clone(),
is_recursive: false,
};
recursion_detector.visit_block(&func.block);
if recursion_detector.is_recursive {
self.recursive_depth = 1;
}
self.visit_block(&func.block);
let mut complexity = self.current_path_complexity.clone();
if self.recursive_depth > 0 {
complexity = match complexity {
Complexity::O1 => Complexity::ON, Complexity::ON => Complexity::ON2, _ => Complexity::OExp, };
}
self.function_complexities.insert(name, complexity.clone());
complexity
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn analyze_loop_pattern(&self, loop_expr: &syn::ExprForLoop) -> Complexity {
if let syn::Expr::Range(range) = &*loop_expr.expr {
return self.analyze_range_complexity(range);
}
if self.is_iterator_pattern(&loop_expr.expr) {
return Complexity::ON;
}
Complexity::ON
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
fn analyze_range_complexity(&self, range: &syn::ExprRange) -> Complexity {
if self.is_logarithmic_range(range) {
return Complexity::OLogN;
}
Complexity::ON
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
fn is_logarithmic_range(&self, _range: &syn::ExprRange) -> bool {
false
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
fn is_iterator_pattern(&self, expr: &Expr) -> bool {
match expr {
Expr::MethodCall(call) => {
let method = call.method.to_string();
matches!(method.as_str(), "iter" | "into_iter" | "iter_mut")
}
_ => false,
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
fn is_sorting_algorithm(&self, func: &syn::ItemFn) -> bool {
let name = func.sig.ident.to_string();
name.contains("sort") || name.contains("heap") || name.contains("quick")
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
fn is_search_algorithm(&self, func: &syn::ItemFn) -> bool {
let name = func.sig.ident.to_string();
name.contains("search") || name.contains("find") || name.contains("binary")
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
fn is_graph_algorithm(&self, func: &syn::ItemFn) -> bool {
let name = func.sig.ident.to_string();
name.contains("dfs") || name.contains("bfs") || name.contains("dijkstra")
}
}