From 46a29db3cbda352c4442faa33e6b16f89f107ace Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 21:11:45 +0300 Subject: [PATCH 1/4] Initial commit with task details for issue #43 Adding CLAUDE.md with task information for AI processing. This file will be removed when the task is complete. Issue: https://github.com/linksplatform/RegularExpressions.Transformer.CSharpToCpp/issues/43 --- CLAUDE.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d351973 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/linksplatform/RegularExpressions.Transformer.CSharpToCpp/issues/43 +Your prepared branch: issue-43-ad881586 +Your prepared working directory: /tmp/gh-issue-solver-1757787100908 + +Proceed. \ No newline at end of file From 4134bab5f2001dbbc9a2e11b8e80ec2bd1e91fa0 Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 21:20:28 +0300 Subject: [PATCH 2/4] Research alternative solutions for C# to C++ transformation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Investigated alternative approaches discussed in Habr article: 1. Smart pointers with reference counting (chosen approach) 2. Garbage collection for C++ (rejected) 3. Static analysis (dismissed) Created comprehensive documentation and working examples: - Literature review of memory management strategies - Comparison of existing C# to C++ transformation tools - Demonstration of smart pointer approaches - Analysis of current regex-based transformation method - Working C++ and Python code examples Key findings: - Smart pointer approach balances automation with performance - Current regex method works well for syntax transformation - AST-based approaches could enhance semantic understanding - Memory management is critical for C#/C++ transformation quality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- experiments/alternative-solutions-research.md | 156 +++++++ experiments/memory-management-examples.cpp | 237 ++++++++++ experiments/simple-memory-demo.cpp | 200 +++++++++ .../transformation-alternatives-demo.py | 415 ++++++++++++++++++ 4 files changed, 1008 insertions(+) create mode 100644 experiments/alternative-solutions-research.md create mode 100644 experiments/memory-management-examples.cpp create mode 100644 experiments/simple-memory-demo.cpp create mode 100644 experiments/transformation-alternatives-demo.py 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/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/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 From ee90483eea7e57eb9443d6407c27b84b468a8c9f Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 21:21:09 +0300 Subject: [PATCH 3/4] 'Auto-commit changes made by Claude MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude ' --- experiments/memory_demo | Bin 0 -> 109024 bytes experiments/simple_demo | Bin 0 -> 56616 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100755 experiments/memory_demo create mode 100755 experiments/simple_demo diff --git a/experiments/memory_demo b/experiments/memory_demo new file mode 100755 index 0000000000000000000000000000000000000000..88fe3559e7b9df1f9bb76cc63824d6be5bea506c GIT binary patch literal 109024 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

fM?T5HLS3zfms47#j9i+OR86cN*a#tK|W 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 literal 0 HcmV?d00001 diff --git a/experiments/simple_demo b/experiments/simple_demo new file mode 100755 index 0000000000000000000000000000000000000000..8f57d0fba793a9e8e20eefe0ce6fe42d15d234f1 GIT binary patch literal 56616 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 tKc&BF*HOSJ-6f~|ciDB!r&{ueIO#Qy*Q literal 0 HcmV?d00001 From b5e81474f04f6f1870bccc5997be90babf5479ae Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 21:21:10 +0300 Subject: [PATCH 4/4] Remove CLAUDE.md - Claude command completed --- CLAUDE.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index d351973..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/linksplatform/RegularExpressions.Transformer.CSharpToCpp/issues/43 -Your prepared branch: issue-43-ad881586 -Your prepared working directory: /tmp/gh-issue-solver-1757787100908 - -Proceed. \ No newline at end of file