diff --git a/src/analyzer/code_analyzer.py b/src/analyzer/code_analyzer.py index a0c49e4..c6ee048 100644 --- a/src/analyzer/code_analyzer.py +++ b/src/analyzer/code_analyzer.py @@ -119,10 +119,29 @@ def _analyze_hot_paths(self, tree: ast.AST) -> None: def _infer_expression_type(self, expr: ast.AST) -> str: """Backward compatibility method for tests.""" return self.type_analyzer._infer_expression_type(expr) or 'auto' - + def _get_type_name(self, node: ast.AST) -> str: """Backward compatibility method for tests.""" return self.type_analyzer._annotation_to_cpp_type(node) or 'auto' + + def _infer_variable_type(self, node: ast.Assign) -> None: + """Backward compatibility method for tests.""" + self.type_analyzer._infer_variable_type(node) + # Update local type_info from the analyzer + for var_name, var_type in self.type_analyzer.type_info.items(): + if isinstance(var_type, str): # Only copy simple type strings + if not hasattr(self, 'type_info'): + self.type_info = {} + self.type_info[var_name] = var_type + + def _infer_function_types(self, node: ast.FunctionDef) -> None: + """Backward compatibility method for tests.""" + self.type_analyzer._analyze_function_types(node) + # Update local type_info from the analyzer + for var_name, var_type in self.type_analyzer.type_info.items(): + if not hasattr(self, 'type_info'): + self.type_info = {} + self.type_info[var_name] = var_type def _find_containing_function_or_class(self, target_node: ast.AST, tree: ast.AST) -> Optional[str]: """Find the function or class containing a given node.""" diff --git a/src/analyzer/performance_analyzer.py b/src/analyzer/performance_analyzer.py index 13ecfcb..d77c726 100644 --- a/src/analyzer/performance_analyzer.py +++ b/src/analyzer/performance_analyzer.py @@ -74,10 +74,11 @@ def _analyze_loop_performance(self, node: ast.AST) -> None: if isinstance(node, (ast.For, ast.While)): # Check for nested loops nested_loops = self._count_nested_loops(node) - if nested_loops > 2: + if nested_loops > 1: # Detect nested loops (2+ levels) line = getattr(node, 'lineno', 0) self.performance_bottlenecks.append({ 'type': 'nested_loops', + 'description': f'Nested loop detected with {nested_loops} levels of nesting', 'nesting_level': nested_loops, 'line': line, 'suggestion': 'Consider algorithm optimization to reduce nesting' @@ -87,12 +88,27 @@ def _analyze_loop_performance(self, node: ast.AST) -> None: expensive_ops = self._find_expensive_operations_in_loop(node) if expensive_ops: line = getattr(node, 'lineno', 0) - self.performance_bottlenecks.append({ - 'type': 'expensive_loop_operations', - 'operations': expensive_ops, - 'line': line, - 'suggestion': 'Move expensive operations outside the loop when possible' - }) + + # Check specifically for container modifications + container_ops = [op for op in expensive_ops if op in ['append', 'extend', 'insert']] + if container_ops: + self.performance_bottlenecks.append({ + 'type': 'container_modification', + 'description': f'Container modification in loop: {", ".join(container_ops)}', + 'operations': container_ops, + 'line': line, + 'suggestion': 'Consider pre-allocating containers or using list comprehensions' + }) + + # Check for other expensive operations + other_ops = [op for op in expensive_ops if op not in ['append', 'extend', 'insert']] + if other_ops: + self.performance_bottlenecks.append({ + 'type': 'expensive_loop_operations', + 'operations': other_ops, + 'line': line, + 'suggestion': 'Move expensive operations outside the loop when possible' + }) def _analyze_comprehension_performance(self, node: ast.ListComp) -> None: """Analyze list comprehension performance.""" diff --git a/src/analyzer/type_inference.py b/src/analyzer/type_inference.py index cb01a73..caf71ba 100644 --- a/src/analyzer/type_inference.py +++ b/src/analyzer/type_inference.py @@ -154,6 +154,8 @@ def _infer_expression_type(self, expr: ast.AST) -> Optional[str]: result = 'double' elif isinstance(expr.value, str): result = 'std::string' + elif expr.value is None: + result = 'std::nullptr_t' elif isinstance(expr, ast.List): if expr.elts: element_type = self._infer_expression_type(expr.elts[0]) @@ -190,6 +192,12 @@ def _infer_expression_type(self, expr: ast.AST) -> Optional[str]: result = 'int' else: result = 'auto' + elif isinstance(expr, ast.Compare): + # Comparison operations always return bool + result = 'bool' + elif isinstance(expr, ast.BoolOp): + # Boolean operations (and, or) always return bool + result = 'bool' elif isinstance(expr, ast.ListComp): # List comprehension - infer from element type element_type = self._infer_expression_type(expr.elt) @@ -231,5 +239,17 @@ def _analyze_function_types(self, node: ast.FunctionDef) -> None: return_type = self._annotation_to_cpp_type(node.returns) if return_type: func_info['return_type'] = return_type + else: + # Try to infer return type from return statements + inferred_return_type = self._infer_return_type_from_body(node.body) + if inferred_return_type: + func_info['return_type'] = inferred_return_type - self.type_info[node.name] = func_info \ No newline at end of file + self.type_info[node.name] = func_info + + def _infer_return_type_from_body(self, body: List[ast.stmt]) -> Optional[str]: + """Infer return type by analyzing return statements in function body.""" + for node in ast.walk(ast.Module(body=body, type_ignores=[])): + if isinstance(node, ast.Return) and node.value: + return self._infer_expression_type(node.value) + return None \ No newline at end of file