From 70a8bffd81be34b692d21e3b2d67f8b19ef9462f Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 12:07:24 +0300 Subject: [PATCH 1/4] Initial commit with task details for issue #63 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/63 --- 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..2fa410a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,5 @@ +Issue to solve: https://github.com/linksplatform/RegularExpressions.Transformer.CSharpToCpp/issues/63 +Your prepared branch: issue-63-aa820fe7 +Your prepared working directory: /tmp/gh-issue-solver-1757754440079 + +Proceed. \ No newline at end of file From 6d23d77442654bcd42be3fb49abb771bda224d6e Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 12:19:14 +0300 Subject: [PATCH 2/4] Use safe specialization for C++ functors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace unsafe std namespace specializations with safe template specialization syntax: - Changed from 'namespace std { template<...> struct hash {...} }' - To 'template<...> struct std::hash {...}' This addresses issue #63 by using the safer approach that avoids namespace pollution and ADL issues. Changes made in both C# and Python implementations: - CSharpToCppTransformer.cs: Updated regex to generate safe syntax - cs2cpp.py: Updated SubRule to generate safe syntax - Added test case to verify the transformation works correctly šŸ¤– Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../CSharpToCppTransformerTests.cs | 29 +++++++++++++++++++ .../CSharpToCppTransformer.cs | 4 +-- python/cs2cpp/cs2cpp.py | 4 +-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs index edca381..94dfac7 100644 --- a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs +++ b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp.Tests/CSharpToCppTransformerTests.cs @@ -35,5 +35,34 @@ public static void Main(string[] args) var actualResult = transformer.Transform(helloWorldCode); Assert.Equal(expectedResult, actualResult); } + + [Fact] + public void SafeHashSpecializationTest() + { + const string inputCode = @" +namespace Platform.Ranges +{ + template struct Range + { + T Minimum; + T Maximum; + + public: override std::int32_t GetHashCode() + { + return {Minimum, Maximum}.GetHashCode(); + } + }; +}"; + var transformer = new CSharpToCppTransformer(); + var actualResult = transformer.Transform(inputCode); + + // Should generate safe specialization syntax + Assert.Contains("template ", actualResult); + Assert.Contains("struct std::hash>", actualResult); + + // Should NOT contain unsafe namespace std opening + Assert.DoesNotContain("namespace std\n{", actualResult); + Assert.DoesNotContain("namespace std {", actualResult); + } } } diff --git a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs index 2f5dceb..a2b2c39 100644 --- a/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs +++ b/csharp/Platform.RegularExpressions.Transformer.CSharpToCpp/CSharpToCppTransformer.cs @@ -578,8 +578,8 @@ public class CSharpToCppTransformer : TextTransformer (new Regex(@"(?\r?\n(?[\t ]*)template [^\n]+)> (struct|class) (?[a-zA-Z0-9]+<\k>)(\s*:\s*[^{\n]+)?[\t ]*(\r?\n)?[\t ]*{)(?(.|\n)*)(?(?<=\r?\n)\k)(?};)"), "${classDeclarationBegin}/*~start~type~${type}~${typeParameter}~*/${middle}${endIndent}/*~end~type~${type}~${typeParameter}~*/${end}", 0), // Inside the scope replace: // /*~start~namespace~Platform::Ranges~*/ ... /*~start~type~Range~T~*/ ... public: override std::int32_t GetHashCode() { return {Minimum, Maximum}.GetHashCode(); } ... /*~end~type~Range~T~*/ ... /*~end~namespace~Platform::Ranges~*/ - // /*~start~namespace~Platform::Ranges~*/ ... /*~start~type~Range~T~*/ ... /*~end~type~Range~T~*/ ... /*~end~namespace~Platform::Ranges~*/ namespace std { template struct hash> { std::size_t operator()(const Platform::Ranges::Range &obj) const { return {Minimum, Maximum}.GetHashCode(); } }; } - (new Regex(@"(?/\*~start~namespace~(?[^~\n\*]+)~\*/)(?(.|\n)+)(?/\*~start~type~(?[^~\n\*]+)~(?[^~\n\*]+)~\*/)(?(.|\n)+?)(?\r?\n[ \t]*(?(private|protected|public): )override std::int32_t GetHashCode\(\)(\s|\n)*{\s*(?[^\s][^\n]+[^\s])\s*}\s*)(?(.|\n)+?)(?/\*~end~type~\k~\k~\*/)(?(.|\n)+)(?/\*~end~namespace~\k~\*/)}\r?\n"), "${namespaceScopeStart}${betweenStartScopes}${typeScopeStart}${before}${after}${typeScopeEnd}${betweenEndScopes}${namespaceScopeEnd}}" + Environment.NewLine + Environment.NewLine + "namespace std" + Environment.NewLine + "{" + Environment.NewLine + " template " + Environment.NewLine + " struct hash<${namespace}::${type}>" + Environment.NewLine + " {" + Environment.NewLine + " std::size_t operator()(const ${namespace}::${type} &obj) const" + Environment.NewLine + " {" + Environment.NewLine + " /*~start~method~*/${methodBody}/*~end~method~*/" + Environment.NewLine + " }" + Environment.NewLine + " };" + Environment.NewLine + "}" + Environment.NewLine, 10), + // /*~start~namespace~Platform::Ranges~*/ ... /*~start~type~Range~T~*/ ... /*~end~type~Range~T~*/ ... /*~end~namespace~Platform::Ranges~*/ template struct std::hash> { std::size_t operator()(const Platform::Ranges::Range &obj) const { return {Minimum, Maximum}.GetHashCode(); } }; + (new Regex(@"(?/\*~start~namespace~(?[^~\n\*]+)~\*/)(?(.|\n)+)(?/\*~start~type~(?[^~\n\*]+)~(?[^~\n\*]+)~\*/)(?(.|\n)+?)(?\r?\n[ \t]*(?(private|protected|public): )override std::int32_t GetHashCode\(\)(\s|\n)*{\s*(?[^\s][^\n]+[^\s])\s*}\s*)(?(.|\n)+?)(?/\*~end~type~\k~\k~\*/)(?(.|\n)+)(?/\*~end~namespace~\k~\*/)}\r?\n"), "${namespaceScopeStart}${betweenStartScopes}${typeScopeStart}${before}${after}${typeScopeEnd}${betweenEndScopes}${namespaceScopeEnd}}" + Environment.NewLine + Environment.NewLine + "template " + Environment.NewLine + "struct std::hash<${namespace}::${type}>" + Environment.NewLine + "{" + Environment.NewLine + " std::size_t operator()(const ${namespace}::${type} &obj) const" + Environment.NewLine + " {" + Environment.NewLine + " /*~start~method~*/${methodBody}/*~end~method~*/" + Environment.NewLine + " }" + Environment.NewLine + "};" + Environment.NewLine, 10), // Inside scope of /*~start~method~*/ replace: // /*~start~method~*/ ... Minimum ... /*~end~method~*/ // /*~start~method~*/ ... obj.Minimum ... /*~end~method~*/ diff --git a/python/cs2cpp/cs2cpp.py b/python/cs2cpp/cs2cpp.py index 44ab7bb..64a4466 100644 --- a/python/cs2cpp/cs2cpp.py +++ b/python/cs2cpp/cs2cpp.py @@ -577,8 +577,8 @@ def __init__( SubRule(r"(?P\r?\n(?P[\t ]*)template [^\n]+)> (struct|class) (?P[a-zA-Z0-9]+<\k>)(\s*:\s*[^{\n]+)?[\t ]*(\r?\n)?[\t ]*{)(?P(.|\n)*)(?P(?<=\r?\n)\k)(?P};)", r"\g/*~start~type~\g~\g~*/\g\g/*~end~type~\g~\g~*/\g", max_repeat=0), # Inside the scope replace: # /*~start~namespace~Platform::Ranges~*/ ... /*~start~type~Range~T~*/ ... public: override std::int32_t GetHashCode() { return {Minimum, Maximum}.GetHashCode(); } ... /*~end~type~Range~T~*/ ... /*~end~namespace~Platform::Ranges~*/ - # /*~start~namespace~Platform::Ranges~*/ ... /*~start~type~Range~T~*/ ... /*~end~type~Range~T~*/ ... /*~end~namespace~Platform::Ranges~*/ namespace std { template struct hash> { std::size_t operator()(const Platform::Ranges::Range &obj) const { return {Minimum, Maximum}.GetHashCode(); } }; } - SubRule(r"(?P/\*~start~namespace~(?P[^~\n\*]+)~\*/)(?P(.|\n)+)(?P/\*~start~type~(?P[^~\n\*]+)~(?P[^~\n\*]+)~\*/)(?P(.|\n)+?)(?P\r?\n[ \t]*(?P(private|protected|public): )override std::int32_t GetHashCode\(\)(\s|\n)*{\s*(?P[^\s][^\n]+[^\s])\s*}\s*)(?P(.|\n)+?)(?P/\*~end~type~\k~\k~\*/)(?P(.|\n)+)(?P/\*~end~namespace~\k~\*/)}\r?\n", r"\g\g\g\g\g\g\g\g}\n" + "\nnamespace std\n" + "{\n" + " template >\n" + " struct hash<\g::\g>\n" + " {\n" + " std::size_t operator()(const \g::\g &obj) const\n" + " {\n" + " /*~start~method~*/\g/*~end~method~*/\n" + " }\n" + " };\n" + "}\n", max_repeat=10), + # /*~start~namespace~Platform::Ranges~*/ ... /*~start~type~Range~T~*/ ... /*~end~type~Range~T~*/ ... /*~end~namespace~Platform::Ranges~*/ template struct std::hash> { std::size_t operator()(const Platform::Ranges::Range &obj) const { return {Minimum, Maximum}.GetHashCode(); } }; + SubRule(r"(?P/\*~start~namespace~(?P[^~\n\*]+)~\*/)(?P(.|\n)+)(?P/\*~start~type~(?P[^~\n\*]+)~(?P[^~\n\*]+)~\*/)(?P(.|\n)+?)(?P\r?\n[ \t]*(?P(private|protected|public): )override std::int32_t GetHashCode\(\)(\s|\n)*{\s*(?P[^\s][^\n]+[^\s])\s*}\s*)(?P(.|\n)+?)(?P/\*~end~type~\k~\k~\*/)(?P(.|\n)+)(?P/\*~end~namespace~\k~\*/)}\r?\n", r"\g\g\g\g\g\g\g\g}\n" + "\ntemplate >\n" + "struct std::hash<\g::\g>\n" + "{\n" + " std::size_t operator()(const \g::\g &obj) const\n" + " {\n" + " /*~start~method~*/\g/*~end~method~*/\n" + " }\n" + "};\n", max_repeat=10), # Inside scope of /*~start~method~*/ replace: # /*~start~method~*/ ... Minimum ... /*~end~method~*/ # /*~start~method~*/ ... obj.Minimum ... /*~end~method~*/ From 6ff2a4588e094894a9a501f53a843da90fca5004 Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 12:19:57 +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 ' --- examples/test_hash_specialization.cs | 13 +++++++++ examples/test_program.cs | 43 ++++++++++++++++++++++++++++ examples/test_transformation.cs | 13 +++++++++ 3 files changed, 69 insertions(+) create mode 100644 examples/test_hash_specialization.cs create mode 100644 examples/test_program.cs create mode 100644 examples/test_transformation.cs diff --git a/examples/test_hash_specialization.cs b/examples/test_hash_specialization.cs new file mode 100644 index 0000000..0c610d2 --- /dev/null +++ b/examples/test_hash_specialization.cs @@ -0,0 +1,13 @@ +namespace Platform.Ranges +{ + public struct Range + { + public T Minimum; + public T Maximum; + + public override int GetHashCode() + { + return {Minimum, Maximum}.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/examples/test_program.cs b/examples/test_program.cs new file mode 100644 index 0000000..11e8629 --- /dev/null +++ b/examples/test_program.cs @@ -0,0 +1,43 @@ +using System; +using Platform.RegularExpressions.Transformer.CSharpToCpp; + +class Program +{ + static void Main() + { + var transformer = new CSharpToCppTransformer(); + + string input = @" +namespace Platform.Ranges +{ + public struct Range + { + public T Minimum; + public T Maximum; + + public override int GetHashCode() + { + return {Minimum, Maximum}.GetHashCode(); + } + } +}"; + + string result = transformer.Transform(input); + Console.WriteLine("===== TRANSFORMED OUTPUT ====="); + Console.WriteLine(result); + + // Check if we have the new safe specialization syntax + if (result.Contains("template ") && result.Contains("struct std::hash<")) + { + Console.WriteLine("\nāœ… SUCCESS: Safe specialization pattern detected!"); + if (!result.Contains("namespace std\n{")) + { + Console.WriteLine("āœ… SUCCESS: No unsafe namespace std usage detected!"); + } + } + else + { + Console.WriteLine("\nāŒ FAILURE: Safe specialization pattern not found!"); + } + } +} \ No newline at end of file diff --git a/examples/test_transformation.cs b/examples/test_transformation.cs new file mode 100644 index 0000000..0186434 --- /dev/null +++ b/examples/test_transformation.cs @@ -0,0 +1,13 @@ +namespace Platform.Ranges +{ + public struct Range + { + public T Minimum { get; set; } + public T Maximum { get; set; } + + public override int GetHashCode() + { + return {Minimum, Maximum}.GetHashCode(); + } + } +} \ No newline at end of file From e5bcfa19eb15ec428716eeb011fa29aaf620391f Mon Sep 17 00:00:00 2001 From: konard Date: Sat, 13 Sep 2025 12:20:01 +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 2fa410a..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,5 +0,0 @@ -Issue to solve: https://github.com/linksplatform/RegularExpressions.Transformer.CSharpToCpp/issues/63 -Your prepared branch: issue-63-aa820fe7 -Your prepared working directory: /tmp/gh-issue-solver-1757754440079 - -Proceed. \ No newline at end of file