diff --git a/experiments/alternative-solutions-research.md b/experiments/alternative-solutions-research.md new file mode 100644 index 0000000..2a4ada6 --- /dev/null +++ b/experiments/alternative-solutions-research.md @@ -0,0 +1,156 @@ +# Alternative Solutions for C# to C++ Code Transformation + +## Research Summary + +This document summarizes alternative solutions for C# to C++ code transformation, as requested in issue #43. The research focuses on three main areas: + +1. Memory management strategies during transformation +2. Alternative transformation tools and approaches +3. Implementation patterns for handling C# runtime features in C++ + +## Memory Management Strategies (from Habr Article Analysis) + +The referenced Habr article (https://habr.com/ru/post/528608/) discusses three main approaches for handling memory management when transforming C# code to C++: + +### 1. Reference Counting with Smart Pointers ✅ (Selected) +- **Approach**: Use smart pointers that track object references +- **Implementation**: Custom "SmartPtr" class that can dynamically switch between strong and weak reference modes +- **Pros**: + - Automatic memory management similar to C# GC + - Deterministic cleanup + - No runtime overhead of garbage collector +- **Cons**: + - Requires handling circular references with weak pointers + - More complex implementation than raw pointers + +### 2. Garbage Collection for C++ ❌ (Rejected) +- **Approach**: Using existing garbage collector like Boehm GC +- **Rejection Reasons**: + - Would impose limitations on client code + - Experiments deemed unsuccessful + - Loss of C++ performance benefits +- **Note**: This approach was quickly dismissed by the original developers + +### 3. Static Analysis ❌ (Dismissed) +- **Approach**: Determine object deletion points through code analysis +- **Rejection Reasons**: + - High algorithm complexity + - Would require analyzing both library and client code + - Not practical for general-purpose transformation + +## Alternative C# to C++ Transformation Tools (2024) + +### Commercial Solutions +1. **CodePorting.Native** + - Professional-grade C# to C++ transformation + - Handles complex scenarios + - Requires payment + +### Open Source Alternatives +1. **AlterNative** - .NET to C++ Translator + - Research project (UPC - BarcelonaTech + AlterAid S.L.) + - Human-like translations from .NET assemblies + - Includes C++ libraries implementing C# runtime classes + - Uses AST transformations + +2. **AI-Based Solutions** + - GitHub Copilot and similar tools + - Good at basic conversion but requires debugging + - Not reliable for production code without manual review + +3. **Manual Conversion Tools** + - Mono platform for cross-platform applications + - PInvoke for interoperability + - IDE features like CodeRush 'smart paste' + +## Current Implementation Analysis + +The current `RegularExpressions.Transformer.CSharpToCpp` project uses: +- **Regex-based transformation rules** for syntax conversion +- **Pattern matching** for C# language constructs +- **Multi-stage processing** (FirstStage, LastStage rules) +- **Both C# and Python implementations** for broader accessibility + +Key transformation patterns observed: +- Namespace conversion (`.` → `::`) +- Access modifier positioning (`public` → `public:`) +- Generic template syntax conversion +- Equality/comparison operations simplification +- Memory management through smart pointer patterns + +## Recommended Alternative Approaches + +### 1. Enhanced AST-Based Transformation +Instead of regex-only approach, consider: +- Parse C# code into Abstract Syntax Tree +- Apply semantic transformations +- Generate C++ code from transformed AST +- Better handling of complex language constructs + +### 2. Hybrid Memory Management Strategy +Combine multiple approaches: +- **Smart pointers** for automatic memory management +- **RAII principles** for resource management +- **Static analysis** for optimization opportunities +- **Weak references** for circular dependency handling + +### 3. Modular Transformation Pipeline +Create pluggable transformation stages: +- **Syntax transformation** (current regex approach) +- **Semantic analysis** (type inference, dependency analysis) +- **Memory management injection** (smart pointer insertion) +- **Optimization passes** (dead code elimination, inlining) + +### 4. Runtime Library Approach +Similar to AlterNative, provide: +- **C++ runtime library** implementing C# BCL classes +- **Memory management utilities** (GC simulation) +- **String handling** (System.String equivalents) +- **Collection classes** (List, Dictionary, etc.) + +## Memory Management Best Practices for Transformation + +### Smart Pointer Strategy +1. **unique_ptr** for single ownership scenarios +2. **shared_ptr** for multiple ownership +3. **weak_ptr** to break circular references +4. **Custom smart pointers** for specific C# patterns + +### Handling C# Patterns in C++ +- **Garbage Collection** → Reference counting with smart pointers +- **Finalizers** → RAII destructors +- **Circular References** → Weak pointer patterns +- **Large Object Heap** → Custom allocators +- **Generations** → Memory pool strategies + +## Performance Considerations + +### C# GC vs C++ Smart Pointers +- **C# GC**: Batch processing, pause times, automatic cycle detection +- **C++ Smart Pointers**: Immediate cleanup, no pauses, manual cycle handling +- **Trade-offs**: Deterministic vs. throughput-optimized memory management + +### Transformation Overhead +- **Regex approach**: Fast but limited semantic understanding +- **AST approach**: Slower but more accurate transformations +- **Hybrid**: Balance between speed and correctness + +## Implementation Recommendations + +Based on this research, the following enhancements could be considered for the current project: + +1. **Memory Management Documentation**: Add explicit documentation about how the current transformation handles memory management patterns + +2. **Smart Pointer Insertion Rules**: Extend current regex rules to automatically insert appropriate smart pointer usage + +3. **Circular Reference Detection**: Add transformation rules to detect and handle potential circular reference scenarios + +4. **Alternative Backend**: Consider implementing an AST-based transformation backend alongside the current regex approach + +5. **Runtime Library**: Develop a companion C++ library that provides C#-like classes and utilities for transformed code + +## Conclusion + +While the current regex-based approach works well for syntax transformation, the research reveals several alternative strategies that could enhance the transformation quality, particularly around memory management. The smart pointer approach from the Habr article aligns well with modern C++ practices and could be integrated into the existing transformation rules. + +The key insight is that effective C# to C++ transformation requires not just syntax conversion, but also semantic understanding of memory management patterns, which suggests a multi-layered approach combining the current regex transformations with additional semantic analysis capabilities. \ No newline at end of file diff --git a/experiments/memory-management-examples.cpp b/experiments/memory-management-examples.cpp new file mode 100644 index 0000000..76bc6bc --- /dev/null +++ b/experiments/memory-management-examples.cpp @@ -0,0 +1,237 @@ +// Memory Management Alternatives for C# to C++ Transformation +// Examples demonstrating the approaches discussed in the Habr article + +#include +#include +#include +#include + +// ============================================================================= +// Alternative 1: Reference Counting with Smart Pointers (Chosen Approach) +// ============================================================================= + +// Custom SmartPtr class that can switch between strong/weak modes +template +class SmartPtr { +private: + std::shared_ptr strong_ptr_; + std::weak_ptr weak_ptr_; + bool is_weak_; + +public: + // Constructor for strong reference + SmartPtr(std::shared_ptr ptr) : strong_ptr_(ptr), is_weak_(false) {} + + // Constructor for weak reference + SmartPtr(std::weak_ptr ptr) : weak_ptr_(ptr), is_weak_(true) {} + + // Convert to weak reference + void makeWeak() { + if (!is_weak_) { + weak_ptr_ = strong_ptr_; + strong_ptr_.reset(); + is_weak_ = true; + } + } + + // Convert to strong reference + bool makeStrong() { + if (is_weak_) { + strong_ptr_ = weak_ptr_.lock(); + if (strong_ptr_) { + is_weak_ = false; + return true; + } + } + return !is_weak_; + } + + // Access the object + T* get() { + if (is_weak_) { + auto locked = weak_ptr_.lock(); + return locked ? locked.get() : nullptr; + } + return strong_ptr_.get(); + } + + // Check if valid + bool isValid() const { + return is_weak_ ? !weak_ptr_.expired() : (strong_ptr_ != nullptr); + } +}; + +// Example class to demonstrate circular reference handling +class Node { +public: + int value; + SmartPtr parent; // This could be weak to break cycles + std::vector> children; // These are strong references + + Node(int val) : value(val), parent(std::shared_ptr(nullptr)) {} + + void addChild(SmartPtr child) { + children.push_back(child); + // Make parent reference weak to avoid cycles - simplified for demo + // In real implementation, this would be handled more elegantly + std::cout << " Added child with value: " << child.get()->value << std::endl; + } +}; + +// ============================================================================= +// Alternative 2: Garbage Collection Approach (Rejected but shown for reference) +// ============================================================================= + +// Simulated GC approach - NOT RECOMMENDED for production +class GCObject { +private: + static std::unordered_set all_objects; + bool marked_for_deletion = false; + +public: + GCObject() { + all_objects.insert(this); + } + + virtual ~GCObject() { + all_objects.erase(this); + } + + // Mark and sweep simulation + static void collectGarbage() { + std::cout << "Simulated garbage collection - NOT RECOMMENDED\n"; + // This is a simplified simulation + for (auto it = all_objects.begin(); it != all_objects.end();) { + if ((*it)->marked_for_deletion) { + delete *it; // This would be problematic in real usage + it = all_objects.erase(it); + } else { + ++it; + } + } + } + + void markForDeletion() { marked_for_deletion = true; } +}; + +std::unordered_set GCObject::all_objects; + +// ============================================================================= +// Alternative 3: Static Analysis Approach (Conceptual) +// ============================================================================= + +// This would require compile-time analysis to determine object lifetimes +// Example shows the concept but static analysis is complex to implement + +template +class AnalyzedPtr { +private: + std::unique_ptr ptr_; + // In real implementation, this would contain lifetime analysis data + +public: + AnalyzedPtr(std::unique_ptr ptr) : ptr_(std::move(ptr)) {} + + // Compiler would insert appropriate cleanup based on static analysis + // This is conceptual - actual implementation would be very complex + T* get() { return ptr_.get(); } +}; + +// ============================================================================= +// Current Approach Demonstration: Standard Smart Pointers +// ============================================================================= + +// Example showing how current C# to C++ transformation handles objects +class CSharpLikeClass { +public: + std::string name; + std::shared_ptr reference; + + CSharpLikeClass(const std::string& n) : name(n) {} + + // Simulating C# property-like access + void setReference(std::shared_ptr ref) { + reference = ref; + } + + std::shared_ptr getReference() { + return reference; + } +}; + +// ============================================================================= +// Demonstration function +// ============================================================================= + +void demonstrateMemoryManagement() { + std::cout << "=== Memory Management Alternatives Demo ===\n\n"; + + // Smart Pointer Approach (Recommended) + std::cout << "1. Smart Pointer Approach:\n"; + auto node1 = std::make_shared(1); + auto node2 = std::make_shared(2); + + SmartPtr smart_node1(node1); + SmartPtr smart_node2(node2); + + // Create parent-child relationship + smart_node1.get()->addChild(smart_node2); + + std::cout << " Created nodes with smart pointer management\n"; + std::cout << " Node1 value: " << smart_node1.get()->value << "\n"; + std::cout << " Node2 value: " << smart_node2.get()->value << "\n\n"; + + // Standard Smart Pointers (Current approach) + std::cout << "2. Standard Smart Pointers (Current):\n"; + auto obj1 = std::make_shared("Object1"); + auto obj2 = std::make_shared("Object2"); + + obj1->setReference(obj2); + + std::cout << " Object1 name: " << obj1->name << "\n"; + std::cout << " Object1 reference: " << obj1->getReference()->name << "\n\n"; + + // GC Approach (Not recommended) + std::cout << "3. GC Approach (NOT RECOMMENDED):\n"; + auto gc_obj = new GCObject(); + gc_obj->markForDeletion(); + GCObject::collectGarbage(); + std::cout << " GC simulation completed\n\n"; + + std::cout << "=== Demo completed ===\n"; +} + +// Main function for testing +int main() { + demonstrateMemoryManagement(); + return 0; +} + +/* +Key Insights from the Examples: + +1. Smart Pointer Approach (Recommended): + - Provides automatic memory management similar to C# GC + - Handles circular references through weak pointers + - Deterministic cleanup without GC pauses + - Can dynamically switch between strong/weak modes + +2. Standard Smart Pointers (Current): + - Uses std::shared_ptr and std::unique_ptr + - Good balance between safety and performance + - Well-supported by modern C++ standard + +3. GC Approach (Rejected): + - Would require significant runtime overhead + - Conflicts with C++ deterministic destruction + - Imposes limitations on client code + +4. Static Analysis (Complex): + - Would require sophisticated compile-time analysis + - Hard to implement for general-purpose transformation + - Would need to analyze both library and client code + +The smart pointer approach from the Habr article represents a good middle ground +between C#'s garbage collection and C++'s manual memory management, providing +automatic cleanup while maintaining C++ performance characteristics. +*/ \ No newline at end of file diff --git a/experiments/memory_demo b/experiments/memory_demo new file mode 100755 index 0000000..88fe355 Binary files /dev/null and b/experiments/memory_demo differ diff --git a/experiments/simple-memory-demo.cpp b/experiments/simple-memory-demo.cpp new file mode 100644 index 0000000..86d6e5e --- /dev/null +++ b/experiments/simple-memory-demo.cpp @@ -0,0 +1,200 @@ +// Simplified Memory Management Demonstration +// Shows the three approaches discussed in the Habr article + +#include +#include +#include + +// ============================================================================= +// Alternative 1: Smart Pointers (Recommended Approach) +// ============================================================================= + +class SmartPtrNode { +public: + int value; + std::weak_ptr parent; // Weak to avoid cycles + std::vector> children; // Strong references + + SmartPtrNode(int val) : value(val) { + std::cout << " SmartPtrNode " << value << " created\n"; + } + + ~SmartPtrNode() { + std::cout << " SmartPtrNode " << value << " destroyed\n"; + } + + void addChild(std::shared_ptr child) { + children.push_back(child); + child->parent = shared_from_this(); + std::cout << " Added child " << child->value << " to parent " << value << "\n"; + } + + // Enable shared_from_this + std::shared_ptr getShared() { + return shared_from_this(); + } + +private: + // Helper for shared_from_this (simplified) + std::shared_ptr shared_from_this() { + // In real code, this would inherit from std::enable_shared_from_this + // For demo, we'll use a different approach + return std::shared_ptr(this, [](SmartPtrNode*){}); // No-op deleter for demo + } +}; + +// ============================================================================= +// Alternative 2: Raw Pointers (Manual Management - Not Recommended) +// ============================================================================= + +class RawPtrNode { +public: + int value; + RawPtrNode* parent; + std::vector children; + + RawPtrNode(int val) : value(val), parent(nullptr) { + std::cout << " RawPtrNode " << value << " created\n"; + } + + ~RawPtrNode() { + std::cout << " RawPtrNode " << value << " destroyed\n"; + // Manual cleanup required + for (auto child : children) { + delete child; + } + } + + void addChild(RawPtrNode* child) { + children.push_back(child); + child->parent = this; + std::cout << " Added child " << child->value << " to parent " << value << "\n"; + } +}; + +// ============================================================================= +// Alternative 3: Reference Counting Simulation +// ============================================================================= + +class RefCountedNode { +private: + int ref_count = 0; + +public: + int value; + RefCountedNode* parent; // Would be weak reference in practice + std::vector children; + + RefCountedNode(int val) : value(val), parent(nullptr) { + std::cout << " RefCountedNode " << value << " created (refs: " << ref_count << ")\n"; + } + + ~RefCountedNode() { + std::cout << " RefCountedNode " << value << " destroyed\n"; + } + + void addRef() { + ref_count++; + std::cout << " RefCountedNode " << value << " refs: " << ref_count << "\n"; + } + + void release() { + ref_count--; + std::cout << " RefCountedNode " << value << " refs: " << ref_count << "\n"; + if (ref_count <= 0) { + delete this; + } + } + + void addChild(RefCountedNode* child) { + children.push_back(child); + child->addRef(); // Add reference + child->parent = this; + std::cout << " Added child " << child->value << " to parent " << value << "\n"; + } +}; + +// ============================================================================= +// Demonstration Functions +// ============================================================================= + +void demonstrateSmartPointers() { + std::cout << "=== Smart Pointers Approach (Recommended) ===\n"; + + // Create nodes using smart pointers + auto root = std::make_shared(1); + auto child1 = std::make_shared(2); + auto child2 = std::make_shared(3); + + // This approach would normally inherit from std::enable_shared_from_this + // For simplicity, we'll just show the concept + std::cout << " Created root and children\n"; + + // Smart pointers automatically handle memory cleanup + std::cout << " Smart pointers will automatically clean up when going out of scope\n"; +} + +void demonstrateRawPointers() { + std::cout << "\n=== Raw Pointers Approach (Manual Management) ===\n"; + + RawPtrNode* root = new RawPtrNode(10); + RawPtrNode* child1 = new RawPtrNode(20); + RawPtrNode* child2 = new RawPtrNode(30); + + root->addChild(child1); + root->addChild(child2); + + std::cout << " Manual cleanup required:\n"; + delete root; // This will delete children too via destructor +} + +void demonstrateRefCounting() { + std::cout << "\n=== Reference Counting Approach ===\n"; + + RefCountedNode* root = new RefCountedNode(100); + root->addRef(); // Initial reference + + RefCountedNode* child = new RefCountedNode(200); + root->addChild(child); // This adds a reference to child + + std::cout << " Releasing references:\n"; + root->release(); // Release root reference + child->release(); // Release child reference (this should delete it) +} + +void demonstrateMemoryManagementComparison() { + std::cout << "\n=== Memory Management Strategy Comparison ===\n"; + + std::cout << "1. Smart Pointers:\n"; + std::cout << " + Automatic memory management\n"; + std::cout << " + Exception safe\n"; + std::cout << " + No memory leaks from circular references (with weak_ptr)\n"; + std::cout << " - Slight overhead from reference counting\n"; + + std::cout << "\n2. Raw Pointers:\n"; + std::cout << " + Maximum performance\n"; + std::cout << " + Direct control over memory\n"; + std::cout << " - Manual memory management required\n"; + std::cout << " - Prone to memory leaks and dangling pointers\n"; + + std::cout << "\n3. Reference Counting:\n"; + std::cout << " + Automatic cleanup when references reach zero\n"; + std::cout << " + Deterministic destruction\n"; + std::cout << " - Cannot handle circular references automatically\n"; + std::cout << " - Need to manually implement reference counting\n"; + + std::cout << "\nThe Habr article chose Smart Pointers with custom SmartPtr class\n"; + std::cout << "that can dynamically switch between strong/weak reference modes.\n"; +} + +int main() { + std::cout << "Memory Management Alternatives for C# to C++ Transformation\n"; + std::cout << "===========================================================\n"; + + demonstrateSmartPointers(); + demonstrateRawPointers(); + demonstrateRefCounting(); + demonstrateMemoryManagementComparison(); + + return 0; +} \ No newline at end of file diff --git a/experiments/simple_demo b/experiments/simple_demo new file mode 100755 index 0000000..8f57d0f Binary files /dev/null and b/experiments/simple_demo differ diff --git a/experiments/transformation-alternatives-demo.py b/experiments/transformation-alternatives-demo.py new file mode 100644 index 0000000..79a7238 --- /dev/null +++ b/experiments/transformation-alternatives-demo.py @@ -0,0 +1,415 @@ +#!/usr/bin/env python3 +""" +Demonstration of Alternative C# to C++ Transformation Approaches +This script shows different strategies beyond the current regex-based approach. +""" + +import re +import ast +from typing import List, Dict, Any +from dataclasses import dataclass + +# ============================================================================= +# Current Approach: Regex-based Transformation (Existing) +# ============================================================================= + +class RegexBasedTransformer: + """Current approach using regex patterns for transformation""" + + def __init__(self): + self.rules = [ + # Basic namespace conversion + (r'namespace\s+([^{]+)', r'namespace \1'), + (r'\.', r'::'), + + # Access modifiers + (r'public\s+(?!class|interface|struct)', r'public: '), + (r'private\s+(?!class|interface|struct)', r'private: '), + + # Smart pointer insertion + (r'(\w+)\s+(\w+)\s*=\s*new\s+\w+\([^)]*\)', r'std::unique_ptr<\1> \2 = std::make_unique<\1>()'), + ] + + def transform(self, csharp_code: str) -> str: + """Apply regex transformations""" + cpp_code = csharp_code + for pattern, replacement in self.rules: + cpp_code = re.sub(pattern, replacement, cpp_code) + return cpp_code + +# ============================================================================= +# Alternative 1: AST-Based Transformation +# ============================================================================= + +@dataclass +class ClassDeclaration: + name: str + members: List[str] + access_modifiers: Dict[str, str] + +@dataclass +class MethodDeclaration: + name: str + return_type: str + parameters: List[str] + body: str + +class ASTBasedTransformer: + """Enhanced approach using abstract syntax tree analysis""" + + def __init__(self): + self.memory_management_strategy = "smart_pointers" + self.include_gc_simulation = False + + def parse_csharp_class(self, csharp_code: str) -> ClassDeclaration: + """Simulate parsing C# class into structured representation""" + # This is a simplified simulation - real implementation would use + # a proper C# parser like Roslyn + + class_match = re.search(r'class\s+(\w+)', csharp_code) + class_name = class_match.group(1) if class_match else "UnknownClass" + + # Extract members (simplified) + members = re.findall(r'(public|private|protected)\s+\w+\s+(\w+)', csharp_code) + + return ClassDeclaration( + name=class_name, + members=[member[1] for member in members], + access_modifiers={member[1]: member[0] for member in members} + ) + + def generate_cpp_class(self, class_decl: ClassDeclaration) -> str: + """Generate C++ class from AST representation""" + cpp_code = f"class {class_decl.name} {{\n" + + # Group by access modifier + access_sections = {"public": [], "private": [], "protected": []} + + for member in class_decl.members: + access = class_decl.access_modifiers.get(member, "private") + + # Apply memory management strategy + if self.memory_management_strategy == "smart_pointers": + member_decl = f" std::unique_ptr {member};" + elif self.memory_management_strategy == "raw_pointers": + member_decl = f" Object* {member};" + else: + member_decl = f" Object {member};" + + access_sections[access].append(member_decl) + + # Generate sections + for access in ["public", "private", "protected"]: + if access_sections[access]: + cpp_code += f"{access}:\n" + cpp_code += "\n".join(access_sections[access]) + "\n" + + cpp_code += "};" + return cpp_code + +# ============================================================================= +# Alternative 2: Memory Management Strategy Injection +# ============================================================================= + +class MemoryManagementInjector: + """Specialized transformer for injecting memory management patterns""" + + def __init__(self, strategy: str = "smart_pointers"): + self.strategy = strategy + self.circular_ref_detector = CircularReferenceDetector() + + def inject_smart_pointers(self, cpp_code: str) -> str: + """Inject smart pointer usage patterns""" + transformations = { + # Convert raw pointer declarations + r'(\w+)\*\s+(\w+)': r'std::unique_ptr<\1> \2', + + # Convert new expressions + r'new\s+(\w+)\(([^)]*)\)': r'std::make_unique<\1>(\2)', + + # Add weak_ptr for potential circular references + # This would require more sophisticated analysis in practice + } + + result = cpp_code + for pattern, replacement in transformations.items(): + result = re.sub(pattern, replacement, result) + + return result + + def inject_gc_simulation(self, cpp_code: str) -> str: + """Inject garbage collection simulation (not recommended)""" + header = """ +// GC simulation headers (NOT RECOMMENDED) +#include +#include + +class GCBase { + static std::unordered_set live_objects; +public: + GCBase() { live_objects.insert(this); } + virtual ~GCBase() { live_objects.erase(this); } + static void collect() { + // Simplified mark-and-sweep simulation + // Real implementation would be much more complex + } +}; +std::unordered_set GCBase::live_objects; + +""" + return header + cpp_code + +# ============================================================================= +# Alternative 3: Circular Reference Detection +# ============================================================================= + +class CircularReferenceDetector: + """Analyze code for potential circular reference patterns""" + + def __init__(self): + self.dependency_graph = {} + + def analyze_dependencies(self, cpp_code: str) -> Dict[str, List[str]]: + """Build dependency graph from code analysis""" + # Simplified analysis - real implementation would be more sophisticated + classes = re.findall(r'class\s+(\w+)', cpp_code) + + for class_name in classes: + # Find member references to other classes + class_section = self.extract_class_section(cpp_code, class_name) + references = re.findall(r'std::(?:unique_ptr|shared_ptr)<(\w+)>', class_section) + self.dependency_graph[class_name] = references + + return self.dependency_graph + + def detect_cycles(self) -> List[List[str]]: + """Detect circular dependencies""" + cycles = [] + visited = set() + rec_stack = set() + + def dfs(node, path): + if node in rec_stack: + # Found cycle + cycle_start = path.index(node) + cycles.append(path[cycle_start:] + [node]) + return + + if node in visited: + return + + visited.add(node) + rec_stack.add(node) + + for neighbor in self.dependency_graph.get(node, []): + dfs(neighbor, path + [node]) + + rec_stack.remove(node) + + for node in self.dependency_graph: + if node not in visited: + dfs(node, []) + + return cycles + + def extract_class_section(self, code: str, class_name: str) -> str: + """Extract the section of code containing a specific class""" + # Simplified extraction + pattern = rf'class\s+{class_name}\s*{{[^}}]*}}' + match = re.search(pattern, code, re.DOTALL) + return match.group(0) if match else "" + +# ============================================================================= +# Alternative 4: Runtime Library Generator +# ============================================================================= + +class RuntimeLibraryGenerator: + """Generate C++ runtime library equivalent to C# BCL classes""" + + def generate_string_class(self) -> str: + """Generate System.String equivalent""" + return """ +// C# System.String equivalent +class String { +private: + std::string data_; + +public: + String(const std::string& str) : data_(str) {} + String(const char* str) : data_(str) {} + + // C# String methods + int Length() const { return data_.length(); } + String Substring(int start) const { return String(data_.substr(start)); } + String Substring(int start, int length) const { + return String(data_.substr(start, length)); + } + bool Contains(const String& other) const { + return data_.find(other.data_) != std::string::npos; + } + String ToUpper() const { + std::string result = data_; + std::transform(result.begin(), result.end(), result.begin(), ::toupper); + return String(result); + } + + // Operators + String operator+(const String& other) const { + return String(data_ + other.data_); + } + bool operator==(const String& other) const { + return data_ == other.data_; + } + + // Conversion + const std::string& toCppString() const { return data_; } +}; +""" + + def generate_list_class(self) -> str: + """Generate System.Collections.Generic.List equivalent""" + return """ +// C# List equivalent +template +class List { +private: + std::vector data_; + +public: + List() = default; + List(std::initializer_list init) : data_(init) {} + + // C# List methods + void Add(const T& item) { data_.push_back(item); } + void Remove(const T& item) { + auto it = std::find(data_.begin(), data_.end(), item); + if (it != data_.end()) data_.erase(it); + } + int Count() const { return data_.size(); } + bool Contains(const T& item) const { + return std::find(data_.begin(), data_.end(), item) != data_.end(); + } + void Clear() { data_.clear(); } + + // Indexer + T& operator[](int index) { return data_[index]; } + const T& operator[](int index) const { return data_[index]; } + + // Iterators for range-based for loops + auto begin() { return data_.begin(); } + auto end() { return data_.end(); } + auto begin() const { return data_.begin(); } + auto end() const { return data_.end(); } +}; +""" + +# ============================================================================= +# Demonstration and Testing +# ============================================================================= + +def demonstrate_alternatives(): + """Demonstrate all alternative approaches""" + + # Sample C# code for transformation + sample_csharp = """ +public class MyClass { + public string Name { get; set; } + private List numbers; + public MyClass reference; + + public MyClass(string name) { + Name = name; + numbers = new List(); + } + + public void AddNumber(int num) { + numbers.Add(num); + } +} +""" + + print("=== C# to C++ Transformation Alternatives Demo ===\n") + + # 1. Current Regex Approach + print("1. Current Regex-based Approach:") + regex_transformer = RegexBasedTransformer() + regex_result = regex_transformer.transform(sample_csharp) + print(regex_result[:200] + "..." if len(regex_result) > 200 else regex_result) + print() + + # 2. AST-based Approach + print("2. AST-based Approach:") + ast_transformer = ASTBasedTransformer() + class_decl = ast_transformer.parse_csharp_class(sample_csharp) + ast_result = ast_transformer.generate_cpp_class(class_decl) + print(ast_result) + print() + + # 3. Memory Management Injection + print("3. Memory Management Strategy Injection:") + mm_injector = MemoryManagementInjector("smart_pointers") + cpp_with_smart_ptrs = mm_injector.inject_smart_pointers(""" + MyClass* obj = new MyClass("test"); + AnotherClass* ref = obj; + """) + print(cpp_with_smart_ptrs) + print() + + # 4. Circular Reference Detection + print("4. Circular Reference Detection:") + detector = CircularReferenceDetector() + sample_cpp_with_refs = """ + class A { + std::shared_ptr b_ref; + }; + class B { + std::shared_ptr a_ref; + }; + """ + dependencies = detector.analyze_dependencies(sample_cpp_with_refs) + cycles = detector.detect_cycles() + print(f"Dependencies: {dependencies}") + print(f"Detected cycles: {cycles}") + print() + + # 5. Runtime Library Generation + print("5. Runtime Library Generation:") + runtime_gen = RuntimeLibraryGenerator() + string_class = runtime_gen.generate_string_class() + print(string_class[:300] + "..." if len(string_class) > 300 else string_class) + + print("\n=== Demo completed ===") + + print(""" +Summary of Alternative Approaches: + +1. Current Regex Approach: + - Fast and simple + - Limited semantic understanding + - Good for syntax transformations + +2. AST-based Approach: + - Better semantic understanding + - More accurate transformations + - Slower but more reliable + +3. Memory Management Injection: + - Specialized for memory safety + - Can handle smart pointer insertion + - Addresses C#/C++ memory model differences + +4. Circular Reference Detection: + - Prevents memory leaks + - Enables weak pointer optimization + - Essential for complex object graphs + +5. Runtime Library: + - Provides C#-like APIs in C++ + - Eases migration burden + - Maintains familiar programming model + +These approaches can be combined for a comprehensive transformation solution. +""") + +if __name__ == "__main__": + demonstrate_alternatives() \ No newline at end of file