diff --git a/.gitignore b/.gitignore index 39f459f0940a..0cc382c65b87 100644 --- a/.gitignore +++ b/.gitignore @@ -190,3 +190,15 @@ Session.vim # VS debug support files launchSettings.json + +# Swift output files +*.swiftinterface* +*.swiftdoc* +*.swiftmodule* +*.abi* +*.swiftsourceinfo* +*.dylib + +# Testing artifacts +testing/ +src/samples/**/*Bindings.cs \ No newline at end of file diff --git a/Directory.Build.targets b/Directory.Build.targets index 05db7dabfa1a..1d7fc8d541b2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -8,7 +8,7 @@ TargetingPackVersion="$(MicrosoftNETCoreAppVersion)" /> - + diff --git a/README.md b/README.md index d865c64af7e3..9ec233973565 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,18 @@ This is a collection of tools designed to consume a compiled Apple Swift library and generate bindings and wrappers that enable it to be used as a .NET library. -## Current Status - -The components are currently undergoing iterative reviews and will be moved from https://github.com/xamarin/binding-tools-for-swift. +## Installation and usage + +The tool will be available as a NuGet CLI package in the [`dotnet-experimental`](https://dev.azure.com/dnceng/public/_packaging?_a=feed&feed=dotnet-experimental) feed. + +Options: +``` + -d, --dylib Required. Path to the dynamic library. + -s, --swiftinterface Required. Path to the Swift interface file. + -o, --output Required. Output directory for generated bindings. + -v, --verbose Information about work in process. + -h, --help Display this help message. +``` ## .NET Foundation diff --git a/SwiftBindings.sln b/SwiftBindings.sln new file mode 100644 index 000000000000..29a0abcea382 --- /dev/null +++ b/SwiftBindings.sln @@ -0,0 +1,132 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftBindings", "src\SwiftBindings\src\SwiftBindings.csproj", "{B7977360-6671-4707-9A1C-1C29D5BE2674}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftBindings.Tests", "src\SwiftBindings\tests\SwiftBindings.Tests.csproj", "{CE81B6BD-CCCC-4223-9069-B28435A4A5C1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftReflector.Tests", "src\SwiftReflector\tests\SwiftReflector.Tests.csproj", "{1C381A63-38D7-4801-97CB-5FA7F683E28A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftReflector", "src\SwiftReflector\src\SwiftReflector.csproj", "{EF015979-24E8-490E-B940-F28988EC5C19}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftRuntimeLibrary", "src\SwiftRuntimeLibrary\src\SwiftRuntimeLibrary.csproj", "{8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftRuntimeLibrary.Tests", "src\SwiftRuntimeLibrary\tests\SwiftRuntimeLibrary.Tests.csproj", "{61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxDynamo", "src\SyntaxDynamo\src\SyntaxDynamo.csproj", "{E05ECC4A-7212-4077-AD30-E4183CA3C1AF}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SyntaxDynamo.Tests", "src\SyntaxDynamo\tests\SyntaxDynamo.Tests.csproj", "{0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x64.ActiveCfg = Debug|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x64.Build.0 = Debug|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x86.ActiveCfg = Debug|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x86.Build.0 = Debug|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|Any CPU.Build.0 = Release|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x64.ActiveCfg = Release|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x64.Build.0 = Release|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x86.ActiveCfg = Release|Any CPU + {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x86.Build.0 = Release|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x64.ActiveCfg = Debug|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x64.Build.0 = Debug|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x86.ActiveCfg = Debug|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x86.Build.0 = Debug|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|Any CPU.Build.0 = Release|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x64.ActiveCfg = Release|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x64.Build.0 = Release|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x86.ActiveCfg = Release|Any CPU + {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x86.Build.0 = Release|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Debug|x64.ActiveCfg = Debug|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Debug|x64.Build.0 = Debug|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Debug|x86.ActiveCfg = Debug|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Debug|x86.Build.0 = Debug|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Release|Any CPU.Build.0 = Release|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Release|x64.ActiveCfg = Release|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Release|x64.Build.0 = Release|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Release|x86.ActiveCfg = Release|Any CPU + {1C381A63-38D7-4801-97CB-5FA7F683E28A}.Release|x86.Build.0 = Release|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Debug|x64.ActiveCfg = Debug|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Debug|x64.Build.0 = Debug|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Debug|x86.ActiveCfg = Debug|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Debug|x86.Build.0 = Debug|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Release|Any CPU.Build.0 = Release|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Release|x64.ActiveCfg = Release|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Release|x64.Build.0 = Release|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Release|x86.ActiveCfg = Release|Any CPU + {EF015979-24E8-490E-B940-F28988EC5C19}.Release|x86.Build.0 = Release|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Debug|x64.ActiveCfg = Debug|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Debug|x64.Build.0 = Debug|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Debug|x86.ActiveCfg = Debug|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Debug|x86.Build.0 = Debug|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Release|Any CPU.Build.0 = Release|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Release|x64.ActiveCfg = Release|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Release|x64.Build.0 = Release|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Release|x86.ActiveCfg = Release|Any CPU + {8E9013BE-01BD-4F4C-8BF7-E8C71FA6608E}.Release|x86.Build.0 = Release|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Debug|x64.ActiveCfg = Debug|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Debug|x64.Build.0 = Debug|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Debug|x86.ActiveCfg = Debug|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Debug|x86.Build.0 = Debug|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Release|Any CPU.Build.0 = Release|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Release|x64.ActiveCfg = Release|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Release|x64.Build.0 = Release|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Release|x86.ActiveCfg = Release|Any CPU + {61F74BC6-1CCA-49FA-B5B8-6C9EABC1D0AB}.Release|x86.Build.0 = Release|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Debug|x64.ActiveCfg = Debug|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Debug|x64.Build.0 = Debug|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Debug|x86.ActiveCfg = Debug|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Debug|x86.Build.0 = Debug|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Release|Any CPU.Build.0 = Release|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Release|x64.ActiveCfg = Release|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Release|x64.Build.0 = Release|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Release|x86.ActiveCfg = Release|Any CPU + {E05ECC4A-7212-4077-AD30-E4183CA3C1AF}.Release|x86.Build.0 = Release|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Debug|x64.ActiveCfg = Debug|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Debug|x64.Build.0 = Debug|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Debug|x86.ActiveCfg = Debug|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Debug|x86.Build.0 = Debug|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Release|Any CPU.Build.0 = Release|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Release|x64.ActiveCfg = Release|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Release|x64.Build.0 = Release|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Release|x86.ActiveCfg = Release|Any CPU + {0C13F0AC-76F1-4FCB-AF42-9CB910A9471B}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/eng/Versions.props b/eng/Versions.props index 96ee7aa47cf3..c8b0dd0ce8ee 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -13,7 +13,7 @@ false 16.7.1 - 2.4.1 + 2.4.2 2.4.3 7.0.0-preview.7.22375.6 diff --git a/eng/pipelines/runtimelab.yml b/eng/pipelines/runtimelab.yml index a2d5f7dda0f4..3d3a7752e8c7 100644 --- a/eng/pipelines/runtimelab.yml +++ b/eng/pipelines/runtimelab.yml @@ -49,16 +49,33 @@ stages: - stage: build displayName: Build jobs: - - template: /eng/pipelines/templates/build-job.yml - parameters: - osGroup: OSX - archType: x64 - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - template: /eng/pipelines/templates/build-job.yml + parameters: + osGroup: OSX + archType: x64 isOfficialBuild: true runTests: false pool: vmImage: 'macOS-latest' + - ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}: + - template: /eng/pipelines/templates/build-job.yml + parameters: + osGroup: OSX + archType: arm64 + runTests: true + pool: + vmImage: 'macOS-latest' + + - template: /eng/pipelines/templates/build-job.yml + parameters: + osGroup: OSX + archType: x64 + runTests: true + pool: + vmImage: 'macOS-latest' + # Publish and validation steps. Only run in official builds - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - template: \eng\common\templates\post-build\post-build.yml diff --git a/global.json b/global.json index ef7775d375fe..c5c66e5ff962 100644 --- a/global.json +++ b/global.json @@ -8,6 +8,6 @@ "dotnet": "8.0.100" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "9.0.0-beta.24102.4" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.22430.3" } } diff --git a/src/SwiftBindings/SwiftBindings.sln b/src/SwiftBindings/SwiftBindings.sln deleted file mode 100644 index 039811c309a5..000000000000 --- a/src/SwiftBindings/SwiftBindings.sln +++ /dev/null @@ -1,48 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26124.0 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftBindings", "src\SwiftBindings.csproj", "{B7977360-6671-4707-9A1C-1C29D5BE2674}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwiftBindings.Tests", "tests\SwiftBindings.Tests.csproj", "{CE81B6BD-CCCC-4223-9069-B28435A4A5C1}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x64.ActiveCfg = Debug|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x64.Build.0 = Debug|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x86.ActiveCfg = Debug|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Debug|x86.Build.0 = Debug|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|Any CPU.Build.0 = Release|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x64.ActiveCfg = Release|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x64.Build.0 = Release|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x86.ActiveCfg = Release|Any CPU - {B7977360-6671-4707-9A1C-1C29D5BE2674}.Release|x86.Build.0 = Release|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x64.ActiveCfg = Debug|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x64.Build.0 = Debug|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x86.ActiveCfg = Debug|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Debug|x86.Build.0 = Debug|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|Any CPU.Build.0 = Release|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x64.ActiveCfg = Release|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x64.Build.0 = Release|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x86.ActiveCfg = Release|Any CPU - {CE81B6BD-CCCC-4223-9069-B28435A4A5C1}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/src/SwiftBindings/src/BindingsCompiler.cs b/src/SwiftBindings/src/BindingsCompiler.cs new file mode 100644 index 000000000000..f39034012665 --- /dev/null +++ b/src/SwiftBindings/src/BindingsCompiler.cs @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; +using SyntaxDynamo.CSLang; +using SwiftReflector.SwiftXmlReflection; +using SwiftReflector.TypeMapping; + +namespace SwiftReflector +{ + public class BindingsCompiler + { + UnicodeMapper UnicodeMapper; + TypeMapper TypeMapper; + FunctionCompiler TLFCompiler; + + public BindingsCompiler() + { + UnicodeMapper = new UnicodeMapper(); + TypeMapper = new TypeMapper(null, UnicodeMapper); + TLFCompiler = new FunctionCompiler(TypeMapper); + } + + public void CompileModule(ModuleDeclaration decl, string outputDirectory, ErrorHandling errors) + { + var namespaceName = $"{decl.Name}Bindings"; + var csNamespace = new CSNamespace(namespaceName); + var csUsingPackages = new CSUsingPackages("System", "System.Runtime.InteropServices"); + var csClass = new CSClass(CSVisibility.Public, decl.Name); + + var csFile = new CSFile(csUsingPackages, new CSNamespace[] { csNamespace }); + csNamespace.Block.Add(csClass); + IEnumerable methods = CompileFunctions(decl.Functions, errors); + csClass.Methods.AddRange(methods); + + string csOutputPath = Path.Combine(outputDirectory, string.Format("{0}.cs", namespaceName)); + CodeWriter.WriteToFile(csOutputPath, csFile); + } + + IEnumerable CompileFunctions(IEnumerable decls, ErrorHandling errors) + { + List methods = new List(); + foreach (FunctionDeclaration decl in decls) + { + var piMethod = TLFCompiler.CompileMethod(decl, true); + methods.Add(piMethod); + var publicMethod = TLFCompiler.CompileMethod(decl, false); + methods.Add(publicMethod); + + var marshaler = new MarshalEngine(null, null, TypeMapper, null); + var lines = marshaler.MarshalFunctionCall(decl, publicMethod, piMethod); + publicMethod.Body.AddRange(lines); + } + + return methods; + } + } +} diff --git a/src/SwiftBindings/src/FunctionCompiler.cs b/src/SwiftBindings/src/FunctionCompiler.cs new file mode 100644 index 000000000000..49202bb6e3fd --- /dev/null +++ b/src/SwiftBindings/src/FunctionCompiler.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo.CSLang; +using SwiftReflector.TypeMapping; +using SwiftReflector.SwiftXmlReflection; + +namespace SwiftReflector +{ + public class FunctionCompiler + { + TypeMapper typeMap; + public FunctionCompiler(TypeMapper typeMap) + { + this.typeMap = typeMap; + } + + public CSMethod CompileMethod(FunctionDeclaration func, bool isPinvoke) + { + string funcName = func.Name; + if (isPinvoke) { + funcName = string.Format("PIfunc_{0}", funcName); + } + + NetTypeBundle returnType = typeMap.MapType(func, func.ReturnTypeSpec, isPinvoke, true); + CSUsingPackages packs = new CSUsingPackages(); + CSType csReturnType = returnType.IsVoid ? CSSimpleType.Void : returnType.ToCSType(packs); + + var csParams = new CSParameterList(); + if (func.ParameterLists.FirstOrDefault().Count > 0){ + var args = typeMap.MapParameterList(func, func.ParameterLists.FirstOrDefault(), isPinvoke, false, null, null, packs); + foreach (var arg in args) + { + var csType = arg.Type.ToCSType(packs); + csParams.Add(new CSParameter(csType, new CSIdentifier(arg.Name), arg.Type.IsReference ? CSParameterKind.Ref : CSParameterKind.None, null)); + } + } + + if (isPinvoke) + { + return CSMethod.InternalPInvoke(csReturnType, funcName, $"lib{func.Module.Name}.dylib", func.MangledName, csParams); + } + else + { + return new CSMethod(CSVisibility.Public, func.IsStatic ? CSMethodKind.Static : CSMethodKind.Virtual, csReturnType, new CSIdentifier(funcName), csParams, new CSCodeBlock()); + } + } + + static void AddUsingBlock(CSUsingPackages packs, NetTypeBundle type) + { + if (type.IsVoid || String.IsNullOrEmpty(type.NameSpace)) + return; + packs.AddIfNotPresent(type.NameSpace); + } + } +} + diff --git a/src/SwiftBindings/src/MarshalEngine.cs b/src/SwiftBindings/src/MarshalEngine.cs new file mode 100644 index 000000000000..924ee17e921e --- /dev/null +++ b/src/SwiftBindings/src/MarshalEngine.cs @@ -0,0 +1,146 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo.CSLang; +using SwiftReflector.TypeMapping; +using SyntaxDynamo; +using SwiftReflector.SwiftXmlReflection; + +namespace SwiftReflector +{ + public class MarshalEngine + { + CSUsingPackages use; + TypeMapper typeMapper; + public bool skipThisParameterPremarshal = false; + List fixedChain = new List(); + Version swiftLangVersion; + public Func genericReferenceNamer = null; + public Func GenericReferenceNamer { get; set; } + + public MarshalEngine(CSUsingPackages use, List identifiersUsed, TypeMapper typeMapper, Version swiftLangVersion) + { + this.use = use; + + this.typeMapper = typeMapper; + this.swiftLangVersion = swiftLangVersion; + } + + public IEnumerable MarshalFunctionCall(FunctionDeclaration decl, CSMethod caller, CSMethod callee) + { + ICodeElement functionCall; + var parms = new CSParameterList(caller.Parameters); + var callParameters = new List(parms.Count); + if (parms.Count > 0) { + var filteredTypeSpec = FilterParams (parms, decl); + for (int i = 0; i < parms.Count; i++) + { + var p = parms[i]; + var originalParm = decl.ParameterLists.Last()[i].TypeSpec; + callParameters.Add(Marshal(null, decl, p, filteredTypeSpec[i], false, + false, originalParm)); + } + } + + var call = new CSFunctionCall(callee.Name.ToString(), false, callParameters.ToArray()); + if (decl.ReturnTypeSpec.Kind != TypeSpecKind.Tuple) + functionCall = CSReturn.ReturnLine((ICSExpression)call); + else + functionCall = new CSLine(call); + + yield return functionCall; + } + + CSParameter ReworkParameterWithNamer(CSParameter p) + { + if (GenericReferenceNamer == null) + return p; + var pClone = ReworkTypeWithNamer(p.CSType); + return new CSParameter(pClone, p.Name, p.ParameterKind, p.DefaultValue); + } + + CSType ReworkTypeWithNamer(CSType ty) + { + if (ty is CSGenericReferenceType genRef) + { + var newGen = new CSGenericReferenceType(genRef.Depth, genRef.Index); + newGen.ReferenceNamer = GenericReferenceNamer; + return newGen; + } + else if (ty is CSSimpleType simple) + { + if (simple.GenericTypes == null) + return simple; + var genSubTypes = new CSType[simple.GenericTypes.Length]; + for (int i = 0; i < genSubTypes.Length; i++) + { + genSubTypes[i] = ReworkTypeWithNamer(simple.GenericTypes[i]); + } + var simpleClone = new CSSimpleType(simple.GenericTypeName, simple.IsArray, genSubTypes); + return simpleClone; + } + else + { + throw new NotImplementedException($"Unable to rework type {ty.GetType().Name} {ty.ToString()} as generic reference"); + } + } + + CSBaseExpression Marshal(BaseDeclaration typeContext, FunctionDeclaration funcDecl, CSParameter p, TypeSpec swiftType, + bool marshalProtocolAsValueType, bool isReturnVariable, TypeSpec originalType) + { + p = ReworkParameterWithNamer(p); + + var entityType = typeMapper.GetEntityTypeForTypeSpec(swiftType); + switch (entityType) + { + case EntityType.Scalar: + return MarshalScalar (p); + case EntityType.Tuple: + case EntityType.None: + // Add more types + break; + } + throw new NotImplementedException($"Uh-oh - not ready for {swiftType.ToString()}, a {entityType}."); + } + + CSBaseExpression MarshalScalar (CSParameter p) + { + return ParmName (p); + } + + static CSIdentifier ParmName (CSParameter parm) + { + return ParmName (parm.Name.Name, parm.ParameterKind); + } + + static CSIdentifier ParmName (string ident, CSParameterKind parmKind) + { + string prefix = ""; + switch (parmKind) { + case CSParameterKind.Out: + prefix = "out "; + break; + case CSParameterKind.Ref: + prefix = "ref "; + break; + default: + break; + } + return new CSIdentifier (String.Format ("{0}{1}", prefix, ident)); + } + + TypeSpec[] FilterParams(CSParameterList parms, FunctionDeclaration decl) + { + var results = new TypeSpec[parms.Count]; + var parameterList = decl.ParameterLists.Last(); + for (int i = 0; i < parms.Count; i++) + { + var currType = parameterList[i].TypeSpec; + results[i] = currType; + } + return results; + } + } +} + diff --git a/src/SwiftBindings/src/MyClass.cs b/src/SwiftBindings/src/MyClass.cs deleted file mode 100644 index 907d856d3f57..000000000000 --- a/src/SwiftBindings/src/MyClass.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace SwiftBindings -{ - public class MyClass - { - public static bool ReturnTrue => true; - public static void Main(string[] args) - { - Console.WriteLine("Hello World!"); - } - } -} diff --git a/src/SwiftBindings/src/Program.cs b/src/SwiftBindings/src/Program.cs new file mode 100644 index 000000000000..c26cd8fc0f0d --- /dev/null +++ b/src/SwiftBindings/src/Program.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.CommandLine; +using SwiftReflector; +using SwiftReflector.Parser; + +namespace SwiftBindings +{ + public class BindingsTool + { + public static void Main(string[] args) + { + Option> swiftAbiOption = new(aliases: new[] { "-a", "--swiftabi" }, "Path to the Swift ABI file.") { AllowMultipleArgumentsPerToken = true, IsRequired = true }; + Option outputDirectoryOption = new(aliases: new[] { "-o", "--output" }, "Output directory for generated bindings.") { IsRequired = true }; + Option verboseOption = new(aliases: new[] { "-v", "--verbose" }, "Prints information about work in process."); + Option helpOption = new(aliases: new[] { "-h", "--help" }, "Display a help message."); + + RootCommand rootCommand = new(description: "Swift bindings generator.") + { + swiftAbiOption, + outputDirectoryOption, + verboseOption, + helpOption, + }; + rootCommand.SetHandler((IEnumerable swiftAbiPaths, string outputDirectory, int verbose, bool help) => + { + if (help) + { + Console.WriteLine("Usage:"); + Console.WriteLine(" -a, --swiftabi Required. Path to the Swift ABI file."); + Console.WriteLine(" -o, --output Required. Output directory for generated bindings."); + Console.WriteLine(" -v, --verbose nformation about work in process."); + return; + } + + if (outputDirectory == string.Empty) + { + Console.Error.WriteLine("Error: Missing required argument(s)."); + return; + } + + for (int i = 0; i < swiftAbiPaths.Count(); i++) + { + string swiftAbiPath = swiftAbiPaths.ElementAt(i); + + if (!File.Exists(swiftAbiPath)) + { + Console.Error.WriteLine($"Error: Swift ABI file not found at path '{swiftAbiPath}'."); + return; + } + + if (verbose > 0) + Console.WriteLine($"Processing Swift ABI file: {swiftAbiPath}"); + + GenerateBindings(swiftAbiPath, outputDirectory, verbose); + } + }, + swiftAbiOption, + outputDirectoryOption, + verboseOption, + helpOption + ); + + rootCommand.Invoke(args); + } + + public static void GenerateBindings(string swiftAbiPath, string outputDirectory, int verbose = 0) + { + if (verbose > 0) + Console.WriteLine("Starting bindings generation..."); + + BindingsCompiler bindingsCompiler = new BindingsCompiler(); + ISwiftParser swiftParser = new SwiftABIParser(); + var errors = new ErrorHandling(); + var decl = swiftParser.GetModuleDeclaration(swiftAbiPath, errors); + + if (verbose > 1) + Console.WriteLine("Parsed Swift ABI file successfully."); + + bindingsCompiler.CompileModule(decl, outputDirectory, errors); + + if (verbose > 0) + Console.WriteLine("Bindings generation completed."); + } + } +} diff --git a/src/SwiftBindings/src/SwiftBindings.csproj b/src/SwiftBindings/src/SwiftBindings.csproj index 91b464afeacc..9b93fe028d76 100644 --- a/src/SwiftBindings/src/SwiftBindings.csproj +++ b/src/SwiftBindings/src/SwiftBindings.csproj @@ -4,7 +4,13 @@ Exe net8.0 enable - enable + disable + + + + + + diff --git a/src/SwiftBindings/tests/CMakeLists.txt b/src/SwiftBindings/tests/CMakeLists.txt new file mode 100644 index 000000000000..67df1e18a089 --- /dev/null +++ b/src/SwiftBindings/tests/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.24) + +project(PInvokeTests) + +set(SOURCE PInvokeTests) + +if (NOT SWIFT_COMPILER_TARGET) + set(SWIFT_PLATFORM "macosx") + if (NOT DEFINED CMAKE_OSX_ARCHITECTURES OR CMAKE_OSX_ARCHITECTURES STREQUAL "") + set(CMAKE_OSX_ARCHITECTURES "${CMAKE_SYSTEM_PROCESSOR}") + endif() + set(SWIFT_DEPLOYMENT_TARGET ${CMAKE_OSX_DEPLOYMENT_TARGET}) + if (NOT DEFINED SWIFT_DEPLOYMENT_TARGET OR SWIFT_DEPLOYMENT_TARGET STREQUAL "") + set(SWIFT_DEPLOYMENT_TARGET "11") + endif() + set(SWIFT_COMPILER_TARGET "${CMAKE_OSX_ARCHITECTURES}-apple-${SWIFT_PLATFORM}${SWIFT_DEPLOYMENT_TARGET}") +endif() + +add_custom_target(${SOURCE} ALL + COMMAND xcrun swiftc -target ${SWIFT_COMPILER_TARGET} -emit-module -emit-library -enable-library-evolution -emit-module-interface ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}.swift -o ${CMAKE_CURRENT_BINARY_DIR}/lib${SOURCE}.dylib + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}.swift + COMMENT "Generating ${SOURCE} library" +) + +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lib${SOURCE}.dylib + DESTINATION bin +) diff --git a/src/SwiftBindings/tests/PInvokeTests.cs b/src/SwiftBindings/tests/PInvokeTests.cs new file mode 100644 index 000000000000..d9d99dfbf256 --- /dev/null +++ b/src/SwiftBindings/tests/PInvokeTests.cs @@ -0,0 +1,3211 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using Xunit; + +namespace SwiftBindings.Tests +{ + public class PInvokeTests + { + [Fact] + public static void TestSwiftFunc0() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc0: "); + long result = PInvokeTests.swiftFunc0(233837, -19649, 949339914140650, 515944430, 3611910812477598, 1366498001922882872, 253, 36322, 9433, 4255310654111403863); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7706330218351441791, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc1() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc1: "); + long result = PInvokeTests.swiftFunc1(86085159640584, 8266931072168309631, 1110349398, 923925690, 37808, unchecked((nint)1505729412738639024), unchecked((nint)5378706168286662479), unchecked((nuint)3649715618139795268), 7849893551470522942, 56451, 91, unchecked((nuint)8878053038747921600), 50562, 51, 1727716, -7397, 1565437348, 5586083, 51673832327441982, 1640275483742190655, 242); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-3202601456867082324, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc2() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc2: "); + long result = PInvokeTests.swiftFunc2(21, 103, 71, 1424520637, 3182953, 59237, 5358256, 185, unchecked((nuint)5971751687364786332), 3252957756581813, 60, 156, 37, 691169209662368818, 619972957, -24591, 1750310134967048045, 3556371, 7350716211230827055, 752486, 13160, 4120692058630618283, 339525547); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(911474180935535301, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc3() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc3: "); + long result = PInvokeTests.swiftFunc3(11017, unchecked((nuint)3300243067329724866), unchecked((nint)2197054130026496019), 7, unchecked((nuint)4243803136497835975)); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-6350065034291914241, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc4() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc4: "); + long result = PInvokeTests.swiftFunc4(123, 109509832281030, 771052005, unchecked((nint)949115070174941197), 409146992556708, 142, 8802835909468694407, 117, 1991550650, 355009119770696130, -1465, 77, 4978285795473493480, 29393, 35783, unchecked((nuint)465708604896456642), unchecked((nint)6140690449828087415), unchecked((nuint)54183433686440276)); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-9091922861563963282, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc5() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc5: "); + long result = PInvokeTests.swiftFunc5(unchecked((nint)6739098280890594874), unchecked((nuint)3195600522343554291), 6597877, unchecked((nint)4743060745349392976), 47478, 51136, 685135916, 1498506, unchecked((nint)2513390154774344247), unchecked((nint)6264911547639833584), 97, 172, -1012, 2975748462028333845); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-3357359150345247842, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc6() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc6: "); + long result = PInvokeTests.swiftFunc6(352858064, 39960, unchecked((nuint)8213487426461212263), unchecked((nuint)8748652475782254131), 4373843, -89, 7725301, 36, 137871115990745445, 114855981505908); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-581969692498632062, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc7() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc7: "); + long result = PInvokeTests.swiftFunc7(unchecked((nint)2299287859300346739), 1631989942, 1588438125, 46916, -25, unchecked((nint)2434879470176610838), 1297396924186241, 1780608786176839, unchecked((nint)3111883344385004599), 10818, 1339461357, 8225377, 313504081, 795664767, 40); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(4054341816496194551, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc8() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc8: "); + long result = PInvokeTests.swiftFunc8(1204549800782266009, -77, 7140941, 5572502, 2067454162041872, 676469398821009314, unchecked((nint)1357719795588198527), -32374, unchecked((nint)3415487707327485172), 3903084861204809, 845624, 90, 1986654521, 114, 214); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-2147505143518021575, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc9() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc9: "); + long result = PInvokeTests.swiftFunc9(unchecked((nint)3705651731235919791), unchecked((nint)8105306104169745115), 6731, 1253260485, unchecked((nuint)8727468328369013450), 5633339905753787255, 651456, 5746290834850613062, 21104, 1670307274); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3533238385513656508, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc10() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc10: "); + long result = PInvokeTests.swiftFunc10(1467110824167985295, 1887615810, 2112733722, 8271177801101005406, 2568471098105086703, 17984, 230, 1774094245, 2124643938); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(8515181823957334780, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc11() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc11: "); + long result = PInvokeTests.swiftFunc11(unchecked((nuint)4085636179246671464), 3081, -79, -13000, 6737190552584399571, 204, -103, 69, 1527509527, 174, 2113159904681342052, unchecked((nint)4901826652984790117), 22029, 7006945911615348711, 1812624423); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-5125817077505710853, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc12() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc12: "); + long result = PInvokeTests.swiftFunc12(6965382, 8312380862312650549, unchecked((nint)9165262159588878385), 17928, 1334453663, -18258, 50575, 1175690859854043654, -1563, 1325, -13033, 109, unchecked((nuint)46750205502198598), 22094, 8206581082498717875, 414098, 43, 1413226877351846990, 3077183154579648); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(4774074602111830179, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc13() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc13: "); + long result = PInvokeTests.swiftFunc13(435831281, unchecked((nint)9152379611666687932), 2121329568, 6151812, 272083164, -25750, 8363795, 2452785801682149491, 70, 1402553126); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(8686515529117439727, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc14() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc14: "); + long result = PInvokeTests.swiftFunc14(2302358859056615, 1148917190, 3948163471413493, 9149629931189885207, unchecked((nuint)8741258279203724116), 1005305, unchecked((nint)4318208587188430868), -120, 3440736986307467027); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(1430703777921650146, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc15() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc15: "); + long result = PInvokeTests.swiftFunc15(257588134824930427, unchecked((nint)8797066708053001900)); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7324810059718518437, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc16() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc16: "); + long result = PInvokeTests.swiftFunc16(18083, 526, unchecked((nint)9092800655449909603), unchecked((nuint)1805357597792116718), 77133128, 4273714158070562, 3356842482838205306, 222, 9005246081447186762, 18718, 4779021523298290196, 265082826573210908, 1651590145, unchecked((nuint)2901617451727386196), 31673, unchecked((nuint)4505812232449759257), 2268590068495235382, 3672721177958656411, 4626146, 206, -70); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-2322427926688559587, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc17() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc17: "); + long result = PInvokeTests.swiftFunc17(776236297300099374, unchecked((nuint)83894503467164568), 719637193271577866, 723625097, 8592004555011333063, -3, 160, -45); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-5704419938581148490, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc18() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc18: "); + long result = PInvokeTests.swiftFunc18(245, unchecked((nint)4458327158518645661), 6050907, 76, unchecked((nint)5568159142839627860), 52, 1144555738, unchecked((nint)8239694963746799753), 148); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7333181440701096551, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc19() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc19: "); + long result = PInvokeTests.swiftFunc19(1964143, unchecked((nuint)7587937485891193274), 8151333634567615027, 17, 170165831807253, 870321007, 98, 1362436055, unchecked((nint)3145994526327645870), 1332381167, 27209, 1960414431895653, 3646108149104658576, 29716, 4480774200926903, 3993989, 831696419130641, 16961, unchecked((nint)2895643089791458731), 9040165725126613424, 4805, 2986899981433626); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7514368921355633465, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc20() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc20: "); + long result = PInvokeTests.swiftFunc20(2304932402575035, 6462973, 1769831413330094805, 38814, 62195, 52028, 643381139480, 240813148, 917778415, -11908, 43571, 735513651, -110, 1706933298, 141); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(4347999520285809529, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc21() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc21: "); + long result = PInvokeTests.swiftFunc21(8204, -18311, 1428916154170345344, 7071281865190759971, 7843802, unchecked((nint)5442642178249643511), 43131, 210, 0, 61711, 104, 6457, 984084882, unchecked((nint)4275598409331185780), unchecked((nuint)8085691827548356926), 387, 1692895, 61, 6740747923378741876, 1508742654); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(9056719667499044372, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc22() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc22: "); + long result = PInvokeTests.swiftFunc22(538154736774388864, 44188, 7266230885340174627, unchecked((nuint)2194770502849252955), 915, 50317); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(2450837469650376012, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc23() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc23: "); + long result = PInvokeTests.swiftFunc23(3154474308016267173, -54, 6973009299557427565, 4709618332502314628, 623782756, 41, 758947939616460266, 38, 2132563794773469419, 696661960811599136, 1159078994, 4596149, 17273, 83, 36422, 3498443323232355); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-6077835106866375633, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc24() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc24: "); + long result = PInvokeTests.swiftFunc24(50216, -31158, 965480864, 31, 1049293008, 8407966859260157806, 20505, 1331992, 4691512, 64675, 7560932795418332291); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7246961535839287248, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc25() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc25: "); + long result = PInvokeTests.swiftFunc25(unchecked((nint)9173857460962505190), 15022, -93, 62197911982761328, 767946476832147, 1436697338, 453782736594733, 8607484193451689185, 1800209635, 6244274, 2230568, 54, 1734973, 4474435427886752355, 668020350438063396, 9113309237687218066); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(4681650148273269479, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc26() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc26: "); + long result = PInvokeTests.swiftFunc26(7995355894864936963, 1657769591981037, 5636685, 49073, 1465261410, 4, 118925102, 1262537, 3410729040016453081, 3116369662775677322, 2298252452836462988, unchecked((nuint)1703297916748788633), 41787, 23); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7896710633380101536, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc27() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc27: "); + long result = PInvokeTests.swiftFunc27(1288789349037378, 246, 2006429802, unchecked((nuint)1682808387624676808), 171, 1097881357975166039, -15744, 74, 561093280, unchecked((nuint)2288145815937670417), 1410177917, 3832322133938261341, 247663832, 6775031520610184090, 343414669, 2137107, unchecked((nint)1607566964681057532), 4327003494555178103, -29278, 6636805788201424308, 5472, 610898910012130); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-2413801917489038945, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc28() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc28: "); + long result = PInvokeTests.swiftFunc28(708394762); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-5115695744450024635, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc29() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc29: "); + long result = PInvokeTests.swiftFunc29(2548726, 185, 23, -27650, 28, 51928, unchecked((nuint)2820244979335896113), 1835, 4050255123891795, 9, 28133, 1603010545626232827, 26825, -3699, unchecked((nuint)9016733266665724964), unchecked((nuint)2189002664079576114), 3158963993105122993, unchecked((nuint)644656289758397492), 7484719451100568914, 41399); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7218188220935660367, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc30() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc30: "); + long result = PInvokeTests.swiftFunc30(2476657055966019, 4347333333421575149, unchecked((nint)7035626728730643182), 246, 330548879, 1030645303, 2185, unchecked((nuint)5053178496758927023), -27715, unchecked((nint)3801555871909422480), 191, unchecked((nint)3437128653478702713), 3235, 1144262746, 3278312, 303215206, 23, 7505126148864499061); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3303407505715961682, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc31() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc31: "); + long result = PInvokeTests.swiftFunc31(186, 5011206654908794290, 1339751659, -14, unchecked((nint)213472320278997211), unchecked((nuint)7645863228691077485), 179117817, 195, -105, 11576, -57, 6980306680077378405, 56); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(6926745355509484660, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc32() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc32: "); + long result = PInvokeTests.swiftFunc32(unchecked((nuint)4591110937711003471), 3095346); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8134759728697468421, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc33() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc33: "); + long result = PInvokeTests.swiftFunc33(427594908988451897, 172944849, 2318725425520920129); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8926062754575499112, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc34() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc34: "); + long result = PInvokeTests.swiftFunc34(7575837, -41, 1617235683, -68, 8522361601751102184, 1353310291, 1751998216661839, 236); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3916199453627741495, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc35() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc35: "); + long result = PInvokeTests.swiftFunc35(657240877, -11, 621151963, 3216313916345125, unchecked((nint)4783457933847136272), -12992, 151); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(4225631615746848021, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc36() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc36: "); + long result = PInvokeTests.swiftFunc36(unchecked((nint)6825261648432495366), 4924311888837579788, unchecked((nint)2728441732713295124), 8539517680162989134, unchecked((nuint)7911109395014469691), 4271690110707692577); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(9029057458451328084, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc37() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc37: "); + long result = PInvokeTests.swiftFunc37(-36, unchecked((nint)95080027562818316), 4100547834833879); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(9091326884382848930, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc38() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc38: "); + long result = PInvokeTests.swiftFunc38(5598802284356856503, 3277053653997566283, 59, 153, 3703517767397116, 48); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(2966780901945169708, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc39() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc39: "); + long result = PInvokeTests.swiftFunc39(-86, 1025206765, unchecked((nint)8854120933376595148), -26660, 1421450910, 1171078919, unchecked((nint)7160130076335475540), 4878908, 3905851, 702664134620078, unchecked((nuint)2925732235852901624), 29717, unchecked((nint)5151891595858119552), 5037163689792046960, -4663, 7608014, 9191594607153046781, 5532); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7464446680392812994, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc40() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc40: "); + long result = PInvokeTests.swiftFunc40(9, 1203576001, 2456300054912747306, 60251, 1342361607567757, 1388115385, 3232188961689180037, 54573633, 1934356798, 5319583380828737022, unchecked((nuint)999425289681850697), 792187764); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-3563617050423332895, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc41() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc41: "); + long result = PInvokeTests.swiftFunc41(8474709311929743705, 12394, unchecked((nint)6127564349538668363), 6333136, 4, 446948525, unchecked((nint)5038104703753360766), 26552, 8206136925734873352, -12, 7199240, unchecked((nuint)8318440149659471267), unchecked((nuint)523184722071542187), 398499589, 1325785459276436, 4573239138788995136, 121, 5590899, 617132760792659437); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-2569382956498289470, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc42() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc42: "); + long result = PInvokeTests.swiftFunc42(8982298576385374275, 16564, unchecked((nint)1565617731878871304), 4419651110224616435, unchecked((nint)7891202001623571444)); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-1108582741386924293, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc43() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc43: "); + long result = PInvokeTests.swiftFunc43(175); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-5808479907339934850, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc44() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc44: "); + long result = PInvokeTests.swiftFunc44(3189698876625689, -18777, 6476950464046275862, 1358084128, 7417, 17593, 610320965697918775, 241147333, 115248210, 4468818817792272374, 17930, 1481953553, -12287, -43, 5647436063971232926); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-234686925954875908, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc45() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc45: "); + long result = PInvokeTests.swiftFunc45(197, 183, 6515265205839958632, 9815, 5707972, -4010, 67, 82, 1832502602, 1685291427109048803, 23310, unchecked((nuint)4680356630874532717), -19307); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-9083497234002976264, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc46() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc46: "); + long result = PInvokeTests.swiftFunc46(579663255922949977, -114, 61, 950773313, 6516, 1526258723168738010, 6992730720599538682); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7467754277704703568, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc47() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc47: "); + long result = PInvokeTests.swiftFunc47(4289393662241141492, 6772140852363500214, 59427, -98); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7149358155385248658, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc48() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc48: "); + long result = PInvokeTests.swiftFunc48(unchecked((nuint)2785520541460599046), 19124, unchecked((nint)3936154413078833457), 2531598, -22, 7611587982378297798, 4886415070100568562, 53, 168, 47, -12, 1408044606511344677, 586995963, unchecked((nint)877805028374247435), 1735610, 1829192187, 798426250350098200); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8590814201057560160, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc49() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc49: "); + long result = PInvokeTests.swiftFunc49(13797); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(739011484971652047, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc50() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc50: "); + long result = PInvokeTests.swiftFunc50(5240299569070422159, 3980, 4966478767025838285, 126, 1448511, 3783312608878806, -32326, 1325886438, 170091605, 1038937165); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3055246540243887734, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc51() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc51: "); + long result = PInvokeTests.swiftFunc51(153365390); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7917142179400080853, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc52() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc52: "); + long result = PInvokeTests.swiftFunc52(49481, unchecked((nuint)2571534213240358460), 19650, 2104528670, 22899, unchecked((nint)8430209965909078811), -25876, 5387620829724391204, unchecked((nint)1450099608276146285), -18049, unchecked((nint)4326178111882457989), 661345047621579, 62960, 239, 3996267746533686661); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8118257769004209257, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc53() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc53: "); + long result = PInvokeTests.swiftFunc53(147266479862857914, unchecked((nint)8878677607688119219), 8593690468919623905, 985107042289460, 3243214921586572926, -18, 5766204873311264178, 2076283, 153, unchecked((nint)4491578823480651614), 31118, 154, 4113143241935276428, 2668467, 2828111477600924337, -48, 822748310022451525, unchecked((nuint)5732324054981972848), unchecked((nint)2079781176213395340), 3554919, 124, unchecked((nint)928745656441981312), -118); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(9075957082830800153, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc54() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc54: "); + long result = PInvokeTests.swiftFunc54(13995, 13570, 7335161404114781494, 21761, 4879059693239079259, 191, -83, 336670981, 5585960, 8626184290788542400, 3677, 1958748094, 127, 3173715667118077320, 33889614420216385, 642796371, 1838551347, 13607283572602918, 6503940653653026899, 52, 4879061834664472526, 4455735786978402948, unchecked((nint)5167060653638148074), -59); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(715458900514912094, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc55() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc55: "); + long result = PInvokeTests.swiftFunc55(2603647622333053765, 4505865605315186666, 109, 96, 10457, 3407618254032143196, 2771970263176123930, 8387065688735342300, 587214218036297943, 47995, -13); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7812796314477300904, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc56() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc56: "); + long result = PInvokeTests.swiftFunc56(unchecked((nuint)4635596573752865036), 872443880, 2315186662326589, 7230035846427727261, 3908289, 400472551, unchecked((nint)1465473227822284563), -31971, unchecked((nuint)2826972572414861403), 3888061765805348, 779414124, 1373494226, 65241, -14, unchecked((nint)800185043394788883), 99, 70223058, -76, 226); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-3660123537755587162, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc57() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc57: "); + long result = PInvokeTests.swiftFunc57(-31909, 6905301, 25023, unchecked((nint)1103857621324234540), 2098823486, 5414734, -11, 926572209, 3200449698799467781, 3679569258896139, 8812281510378648951, unchecked((nuint)4871025154453945009), 152, 62421); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8830493546874923270, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc58() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc58: "); + long result = PInvokeTests.swiftFunc58(unchecked((nint)7967575041279499718), 3232788, 14816036, 3383016995295473, unchecked((nuint)4850027613376762027), unchecked((nint)8327795864754336795), 3340754, -3120, 2761192, 3983147687671529407, 71, 5318708, 1392678309); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(6514055640091085387, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc59() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc59: "); + long result = PInvokeTests.swiftFunc59(44844, unchecked((nuint)1748801304810040008), 30766, unchecked((nuint)4039697629876222207), 1041509849, 58, -4630, 2359663412992532838, 4965740); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(5046324847209516867, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc60() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc60: "); + long result = PInvokeTests.swiftFunc60(1832792349913741, 412903961769194327, 15449); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8176066941526010601, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc61() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc61: "); + long result = PInvokeTests.swiftFunc61(-56, 10, 254, 3947646992575930886, unchecked((nint)1512031355372423197), 376047834, unchecked((nint)1656240652039967673), 22865, 2499705526110532, 44, 1741513168, 221); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8047185703659702100, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc62() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc62: "); + long result = PInvokeTests.swiftFunc62(10, 2075487406, -9981, 168, unchecked((nint)6799443207845790064), 16835, 4246786459783416, 99, 2318900356573254122, 4147579480654007864); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(6758416630263865563, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc63() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc63: "); + long result = PInvokeTests.swiftFunc63(4817099); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-24765264996518815, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc64() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc64: "); + long result = PInvokeTests.swiftFunc64(-31400, 33, 1144995603961263); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(4496411701938139124, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc65() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc65: "); + long result = PInvokeTests.swiftFunc65(343468144996369, 1595701486, 691136339, 377795381, unchecked((nuint)8621456802956657380), 387673204, -79, 684151295, 2702822453080893204, 658117164, 1483498070, 19901, 82, 298593782, 498504311); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7620356050748244213, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc66() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc66: "); + long result = PInvokeTests.swiftFunc66(unchecked((nuint)6742646500239271530), 1283101175, unchecked((nuint)971826232915481756), 6531); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-6837183037573462724, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc67() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc67: "); + long result = PInvokeTests.swiftFunc67(2788572937592617, 59180, 200708656, 9131, 1755490561, 258348099, 254, 779012863187640, 1906037567212321, 544676897, 7911267266539149763, 336384219, 575060377, -11136, 1779482464); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3965211134150981679, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc68() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc68: "); + long result = PInvokeTests.swiftFunc68(99561312221799, 1453132808, 1612303761, unchecked((nint)6043673650667392022), unchecked((nuint)560907030475989979)); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(8645187640386338150, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc69() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc69: "); + long result = PInvokeTests.swiftFunc69(unchecked((nuint)5309972206871421224), 27234, 5023167, 45761, 6425609162827184107); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-2766546132850174765, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc70() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc70: "); + long result = PInvokeTests.swiftFunc70(265213086, 2024995329946372, 99, unchecked((nuint)6130388454564398915), 13675, unchecked((nint)7672787511778724532), 83667695082967, unchecked((nint)8879102379708862673)); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-6730251310408327023, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc71() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc71: "); + long result = PInvokeTests.swiftFunc71(unchecked((nuint)7826726408346018358), 3933082761574796313, 1549799158, 1737163241, 4770998022264795192, 3012307, -22318, 174, 3175654294509651, 7095989, unchecked((nint)2671492835533826745), unchecked((nint)4435595869554769711), 3593089457929161, -70, 12103, 1171000858, 142); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-4761426221194945322, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc72() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc72: "); + long result = PInvokeTests.swiftFunc72(6784686274248571763, 104, unchecked((nint)909285983876097936), 6714220880263670485, 7373872626119376832, -23109, -39, 85, 3722567341893906, 5856612, 11316); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(8722701469163367659, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc73() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc73: "); + long result = PInvokeTests.swiftFunc73(-31440, 1071353143); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(9091436234605144348, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc74() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc74: "); + long result = PInvokeTests.swiftFunc74(8367961236466665848, 3084215, 5133, 881467901, 1349905959, 1058177434, 266815227, 740895977807658292, unchecked((nuint)2510276735562063056), 2731666997695150, 7789234325148051159, 1528039387, 16705, 146766703, 4585584465621462072, 1977); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-4564195959279673945, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc75() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc75: "); + long result = PInvokeTests.swiftFunc75(1027938307, 56236, 88, 98, 27306, 61342909, 2269015579127872, 1031703529, 8402886576148882920, -68, 3807162); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-3369734987080453648, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc76() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc76: "); + long result = PInvokeTests.swiftFunc76(301994950391123, 4344776, 104, 2137807671, 171179011, 3134127914468069876, 6656, 42885, unchecked((nint)7737600182044247158), -120, 1033649432, 129875179286116790); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8920640767423704440, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc77() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc77: "); + long result = PInvokeTests.swiftFunc77(3316166077206800, 3332468478057987249, 1373131825374120, 4918231, 2744065375713515, 3594016966337642259, -60, 20, -106, 2272, 856759296, unchecked((nuint)411883701353980843), unchecked((nint)932327579092391229), 515885, 42, 29247, 2550, 995856082225857); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(6960169366615671879, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc78() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc78: "); + long result = PInvokeTests.swiftFunc78(8691571239579681212, -6331, unchecked((nuint)747809074035744802), unchecked((nint)4660686733629536050), -25591, 6155, 378094, 52, 7080577359538810005, 26362, 1774417260, 144, 5160013); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(4812301631028745377, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc79() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc79: "); + long result = PInvokeTests.swiftFunc79(3768859, 701589732, 49, unchecked((nint)2400132102872573811), 7919338068121439001, 12, 1161810112, 1492596679, 3256298, 150297458, 44, 3359191536348582004, 2501, -3042, 31848, unchecked((nuint)8625178339509965677), 1789284789053154, 6259002624415501110, -23813); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(693619259694162127, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc80() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc80: "); + long result = PInvokeTests.swiftFunc80(2729190792419187, 1585764063, 5117419591579829234, 614117500, 1693556822); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-4631030647197364647, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc81() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc81: "); + long result = PInvokeTests.swiftFunc81(unchecked((nint)8095725324232772887), -11, 1220850298, 2854360776836504, 8343542849265358484, 1016078821622888399, 1083388, 791962662); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8908581242517107527, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc82() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc82: "); + long result = PInvokeTests.swiftFunc82(unchecked((nuint)1174997556571304622), 2990610909261926, 18753, 6253511180087050924, 3058091764587841331, 2842978159455375886); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-1543576629977717704, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc83() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc83: "); + long result = PInvokeTests.swiftFunc83(168003999, 689879558669204554, 3381664931253746938, 82, 2210365248447152, 14007, 50724, 211726992, 4908, 9089, -1517, 793801401, 3942422035006427459, 5203020310498374994, 2464433756321920, 8067802492059811569, 649047218); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-4161389211393419243, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc84() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc84: "); + long result = PInvokeTests.swiftFunc84(5500564689809982598, 8160193010477217516, unchecked((nint)2621562636476726595), 1925518901041551, 833959); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(8984640578940854556, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc85() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc85: "); + long result = PInvokeTests.swiftFunc85(1828548277567665, 79, unchecked((nuint)2816133458526686380), 246, unchecked((nuint)8123936957398843594), 1915634045, 4277399425149259, 4236491, 526249560, -1564, 2077376027144570, 96496756, 3426459, unchecked((nuint)4946835975333850900), -16125, 5180091340514231581, 6830, 8017, 16950, 83); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-5603269280984392717, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc86() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc86: "); + long result = PInvokeTests.swiftFunc86(unchecked((nuint)2690514211977331186), 48174, 5251669033533125188, -41, -118, -26036, 46895, 1006135665982533, -25915, 43319, 4016647159010115823, 161); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-756030944410084256, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc87() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc87: "); + long result = PInvokeTests.swiftFunc87(41821, 2106599750261545766, 493830841784699955, unchecked((nint)7791163656720105501), 25, -15830, 286454392, 8274918093536357376, -18788, 6681672249680875943, 49954076158807243, 78, 3875942, -110, 2697976, 2443700317924383, 4382626); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3151224756940080953, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc88() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc88: "); + long result = PInvokeTests.swiftFunc88(12483, 401268929, -24340, 3584682894830208318, 4149, -28723, -18310, 2621165654927965, unchecked((nuint)4216156540440558538), 2006613843, 6015933, unchecked((nuint)4129107791356788363), 34682, 185, 4770291906992587002, -97, 91, 196); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3274371447309987255, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc89() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc89: "); + long result = PInvokeTests.swiftFunc89(154, unchecked((nint)5210339515636897856), unchecked((nint)3761599239105734389), 18, unchecked((nint)72966313290508081), 4265746, unchecked((nuint)8929551288352689384), -24066, 35491, 2551, unchecked((nint)45491645438357652), 715787386644356803, 4473157306905713, 6702547903250883900, 137061596142255, 4385401769623650480, 3378729933484470887, 1873740829, 8574214966744389441, unchecked((nuint)6446163511298821165), unchecked((nuint)6980694483795543674), 1241824808, 23615, 122); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-737269134554333880, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc90() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc90: "); + long result = PInvokeTests.swiftFunc90(79, 14, 1297542167439891848, 7930448, 975812823, 259332537, 21563, 28989); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(3441802633846719073, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc91() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc91: "); + long result = PInvokeTests.swiftFunc91(6278); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(711186144202003795, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc92() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc92: "); + long result = PInvokeTests.swiftFunc92(18225, 35, 24134, 4453695771230697, 3872995088603792387, unchecked((nint)6499933966838367751), 1330188682, 444420882, unchecked((nint)3796465283221572512), 52249, 7652735, 46441, 1927427838, 1860451970, unchecked((nint)4367540142032169587), 4492446); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(9206890599465525240, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc93() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc93: "); + long result = PInvokeTests.swiftFunc93(5748645559017654978, 5012895573340412455, 6009269000723558276, 2036630461492010444, 2436544965066504769, -125, 112, 52799, -8246, 1830045846, 1191186, 16965, 394617474747610321, 2155653386650409489, 4259466864793291, -118, -32470, -47); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7367909694938381646, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc94() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc94: "); + long result = PInvokeTests.swiftFunc94(unchecked((nuint)8677945289555827317), 6313732, 1990822772, unchecked((nuint)7652693732374651003), unchecked((nint)514619182324762120), 48, unchecked((nuint)4099443960025139442), 1897073213, 27911, 227, unchecked((nuint)3629774823693910128), unchecked((nuint)7475134394365608458), 1341041583, 8490306759261258130); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7957085466204676840, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc95() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc95: "); + long result = PInvokeTests.swiftFunc95(767020, -67, 1994628757624347102, 1066179, 675787169564137362, unchecked((nint)9035231335376355925), 647886678, -12302, unchecked((nuint)6982264019182060207), 55835, 7279581463482143007, unchecked((nuint)541979943210980226), 38516, unchecked((nuint)2405396521289532217), 577291409326865, 5810393543186852048, 5570902738989457385, 5, 6674072748987199349, 6807910446229279331, 70704, 749368364527200140); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-8941275780625427292, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc96() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc96: "); + long result = PInvokeTests.swiftFunc96(492870375181451098, 17857, 2042744158, 2550762577962530718, 2130047, unchecked((nint)7683558322808060031), -76, 85, -42, 8057727507941436393, 182, 44022, 8416140399167561318, 1582924161, 8051228828487128057, 968670026, 1); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(2083246537822351760, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc97() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc97: "); + long result = PInvokeTests.swiftFunc97(16235, 12, 29, -112, 8233611281498306459, 19, 23310, 115438575, unchecked((nuint)4258580046730992269)); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(8647824177212049859, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc98() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc98: "); + long result = PInvokeTests.swiftFunc98(4045, 86, 101013943533129, unchecked((nint)7999096616438753438), unchecked((nuint)7026548990347163237), 165, 1089253429, 164, unchecked((nuint)8255391170515879868), 13496, 5513927, 46, 3217265538715926, 717333105, 50429, -9149); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(7040925530630314472, result); + Console.WriteLine("OK"); + } + + [Fact] + public static void TestSwiftFunc99() + { + BindingsTool.GenerateBindings("PInvokeTests.abi.json", ""); + var sourceCode = """ + // Copyright (c) Microsoft Corporation. + // Licensed under the MIT License. + + using System; + using PInvokeTestsBindings; + + namespace Test { + public class MainClass { + public static int Main(string[] args) + { + return 0; + } + public static long getResult() + { + Console.Write("Running SwiftFunc99: "); + long result = PInvokeTests.swiftFunc99(155, unchecked((nuint)1880700265511668237), 1595962890494032981); + return result; + } + } + } + """; + + long result = (long)TestsHelper.CompileAndExecute("PInvokeTestsBindings.cs", sourceCode, "Test.MainClass", "getResult"); + Assert.Equal(-7883825139759684683, result); + Console.WriteLine("OK"); + } + } +} diff --git a/src/SwiftBindings/tests/PInvokeTests.swift b/src/SwiftBindings/tests/PInvokeTests.swift new file mode 100644 index 000000000000..5fb6851306ad --- /dev/null +++ b/src/SwiftBindings/tests/PInvokeTests.swift @@ -0,0 +1,1700 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import Foundation + +struct HasherFNV1a { + + private var hash: UInt = 14_695_981_039_346_656_037 + private let prime: UInt = 1_099_511_628_211 + + mutating func combine(_ val: T) { + for byte in withUnsafeBytes(of: val, Array.init) { + hash ^= UInt(byte) + hash = hash &* prime + } + } + + func finalize() -> Int { + Int(truncatingIfNeeded: hash) + } +} + +public func swiftFunc0(a0: Float, a1: Int16, a2: Double, a3: Int32, a4: Double, a5: UInt64, a6: UInt8, a7: UInt16, a8: Int16, a9: Int64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + return hasher.finalize() +} + +public func swiftFunc1(a0: Double, a1: Int64, a2: UInt32, a3: UInt32, a4: UInt16, a5: Int, a6: Int, a7: UInt, a8: UInt64, a9: UInt16, a10: UInt8, a11: UInt, a12: UInt16, a13: Int8, a14: Float, a15: Int16, a16: Int32, a17: Float, a18: UInt64, a19: Int64, a20: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + return hasher.finalize() +} + +public func swiftFunc2(a0: UInt8, a1: Int8, a2: Int8, a3: Int32, a4: UInt32, a5: UInt16, a6: Float, a7: UInt8, a8: UInt, a9: Double, a10: UInt8, a11: UInt8, a12: Int8, a13: UInt64, a14: UInt32, a15: Int16, a16: UInt64, a17: Float, a18: Int64, a19: Float, a20: Int16, a21: UInt64, a22: Int32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + hasher.combine(a21); + hasher.combine(a22); + return hasher.finalize() +} + +public func swiftFunc3(a0: Int16, a1: UInt, a2: Int, a3: UInt8, a4: UInt) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + return hasher.finalize() +} + +public func swiftFunc4(a0: UInt8, a1: Double, a2: Int32, a3: Int, a4: Double, a5: UInt8, a6: Int64, a7: Int8, a8: Int32, a9: Int64, a10: Int16, a11: Int8, a12: Int64, a13: UInt16, a14: UInt16, a15: UInt, a16: Int, a17: UInt) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + return hasher.finalize() +} + +public func swiftFunc5(a0: Int, a1: UInt, a2: Float, a3: Int, a4: UInt16, a5: UInt16, a6: UInt32, a7: Float, a8: Int, a9: Int, a10: UInt8, a11: UInt8, a12: Int16, a13: Int64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + return hasher.finalize() +} + +public func swiftFunc6(a0: Int32, a1: UInt16, a2: UInt, a3: UInt, a4: Float, a5: Int8, a6: Float, a7: UInt8, a8: Int64, a9: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + return hasher.finalize() +} + +public func swiftFunc7(a0: Int, a1: Int32, a2: UInt32, a3: UInt16, a4: Int8, a5: Int, a6: Double, a7: Double, a8: Int, a9: UInt16, a10: UInt32, a11: Float, a12: UInt32, a13: Int32, a14: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc8(a0: Int64, a1: Int8, a2: Float, a3: Float, a4: Double, a5: UInt64, a6: Int, a7: Int16, a8: Int, a9: Double, a10: Float, a11: Int8, a12: Int32, a13: Int8, a14: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc9(a0: Int, a1: Int, a2: UInt16, a3: Int32, a4: UInt, a5: Int64, a6: Float, a7: Int64, a8: UInt16, a9: Int32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + return hasher.finalize() +} + +public func swiftFunc10(a0: UInt64, a1: UInt32, a2: UInt32, a3: Int64, a4: UInt64, a5: UInt16, a6: UInt8, a7: Int32, a8: Int32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + return hasher.finalize() +} + +public func swiftFunc11(a0: UInt, a1: UInt16, a2: Int8, a3: Int16, a4: Int64, a5: UInt8, a6: Int8, a7: Int8, a8: UInt32, a9: UInt8, a10: UInt64, a11: Int, a12: Int16, a13: UInt64, a14: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc12(a0: Float, a1: Int64, a2: Int, a3: Int16, a4: Int32, a5: Int16, a6: UInt16, a7: Int64, a8: Int16, a9: UInt16, a10: Int16, a11: UInt8, a12: UInt, a13: UInt16, a14: UInt64, a15: Float, a16: Int8, a17: UInt64, a18: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + return hasher.finalize() +} + +public func swiftFunc13(a0: Int32, a1: Int, a2: UInt32, a3: Float, a4: UInt32, a5: Int16, a6: Float, a7: UInt64, a8: UInt8, a9: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + return hasher.finalize() +} + +public func swiftFunc14(a0: Double, a1: UInt32, a2: Double, a3: UInt64, a4: UInt, a5: Int32, a6: Int, a7: Int8, a8: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + return hasher.finalize() +} + +public func swiftFunc15(a0: UInt64, a1: Int) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + return hasher.finalize() +} + +public func swiftFunc16(a0: Int16, a1: UInt16, a2: Int, a3: UInt, a4: UInt32, a5: Double, a6: UInt64, a7: UInt8, a8: UInt64, a9: Int16, a10: Int64, a11: UInt64, a12: UInt32, a13: UInt, a14: UInt16, a15: UInt, a16: Int64, a17: UInt64, a18: Float, a19: UInt8, a20: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + return hasher.finalize() +} + +public func swiftFunc17(a0: UInt64, a1: UInt, a2: UInt64, a3: UInt32, a4: Int64, a5: Int8, a6: UInt8, a7: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + return hasher.finalize() +} + +public func swiftFunc18(a0: UInt8, a1: Int, a2: Float, a3: UInt8, a4: Int, a5: Int8, a6: UInt32, a7: Int, a8: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + return hasher.finalize() +} + +public func swiftFunc19(a0: Float, a1: UInt, a2: Int64, a3: UInt8, a4: Double, a5: Int32, a6: Int8, a7: Int32, a8: Int, a9: Int32, a10: Int16, a11: Double, a12: Int64, a13: UInt16, a14: Double, a15: Float, a16: Double, a17: Int16, a18: Int, a19: Int64, a20: UInt16, a21: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + hasher.combine(a21); + return hasher.finalize() +} + +public func swiftFunc20(a0: Double, a1: Float, a2: UInt64, a3: Float, a4: UInt16, a5: UInt16, a6: Double, a7: UInt32, a8: UInt32, a9: Int16, a10: UInt16, a11: Int32, a12: Int8, a13: Int32, a14: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc21(a0: Int16, a1: Int16, a2: UInt64, a3: Int64, a4: Float, a5: Int, a6: UInt16, a7: UInt8, a8: Int8, a9: UInt16, a10: Int8, a11: Int16, a12: Int32, a13: Int, a14: UInt, a15: Int16, a16: Float, a17: UInt8, a18: Int64, a19: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + return hasher.finalize() +} + +public func swiftFunc22(a0: Int64, a1: UInt16, a2: UInt64, a3: UInt, a4: UInt16, a5: UInt16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + return hasher.finalize() +} + +public func swiftFunc23(a0: UInt64, a1: Int8, a2: UInt64, a3: Int64, a4: Int32, a5: UInt8, a6: UInt64, a7: Int8, a8: UInt64, a9: Int64, a10: UInt32, a11: Float, a12: Int16, a13: Int8, a14: UInt16, a15: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + return hasher.finalize() +} + +public func swiftFunc24(a0: UInt16, a1: Int16, a2: UInt32, a3: Int8, a4: Int32, a5: Int64, a6: UInt16, a7: Float, a8: Float, a9: UInt16, a10: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + return hasher.finalize() +} + +public func swiftFunc25(a0: Int, a1: Int16, a2: Int8, a3: Int64, a4: Double, a5: UInt32, a6: Double, a7: UInt64, a8: UInt32, a9: Float, a10: Float, a11: Int8, a12: Float, a13: Int64, a14: Int64, a15: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + return hasher.finalize() +} + +public func swiftFunc26(a0: Int64, a1: Double, a2: Float, a3: UInt16, a4: Int32, a5: UInt8, a6: Int32, a7: Float, a8: Int64, a9: Int64, a10: UInt64, a11: UInt, a12: UInt16, a13: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + return hasher.finalize() +} + +public func swiftFunc27(a0: Double, a1: UInt8, a2: UInt32, a3: UInt, a4: UInt8, a5: Int64, a6: Int16, a7: UInt8, a8: UInt32, a9: UInt, a10: UInt32, a11: UInt64, a12: Int32, a13: Int64, a14: Int32, a15: Float, a16: Int, a17: UInt64, a18: Int16, a19: Int64, a20: UInt16, a21: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + hasher.combine(a21); + return hasher.finalize() +} + +public func swiftFunc28(a0: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + return hasher.finalize() +} + +public func swiftFunc29(a0: Float, a1: UInt8, a2: UInt8, a3: Int16, a4: Int8, a5: UInt16, a6: UInt, a7: Int16, a8: Double, a9: Int8, a10: Int16, a11: UInt64, a12: Int16, a13: Int16, a14: UInt, a15: UInt, a16: Int64, a17: UInt, a18: Int64, a19: UInt16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + return hasher.finalize() +} + +public func swiftFunc30(a0: Double, a1: Int64, a2: Int, a3: UInt8, a4: UInt32, a5: Int32, a6: Int16, a7: UInt, a8: Int16, a9: Int, a10: UInt8, a11: Int, a12: Int16, a13: UInt32, a14: Float, a15: UInt32, a16: Int8, a17: Int64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + return hasher.finalize() +} + +public func swiftFunc31(a0: UInt8, a1: Int64, a2: Int32, a3: Int8, a4: Int, a5: UInt, a6: UInt32, a7: UInt8, a8: Int8, a9: Int16, a10: Int8, a11: UInt64, a12: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + return hasher.finalize() +} + +public func swiftFunc32(a0: UInt, a1: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + return hasher.finalize() +} + +public func swiftFunc33(a0: Int64, a1: UInt32, a2: Int64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + return hasher.finalize() +} + +public func swiftFunc34(a0: Float, a1: Int8, a2: UInt32, a3: Int8, a4: UInt64, a5: UInt32, a6: Double, a7: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + return hasher.finalize() +} + +public func swiftFunc35(a0: Int32, a1: Int8, a2: UInt32, a3: Double, a4: Int, a5: Int16, a6: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + return hasher.finalize() +} + +public func swiftFunc36(a0: Int, a1: Int64, a2: Int, a3: UInt64, a4: UInt, a5: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + return hasher.finalize() +} + +public func swiftFunc37(a0: Int8, a1: Int, a2: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + return hasher.finalize() +} + +public func swiftFunc38(a0: UInt64, a1: UInt64, a2: Int8, a3: UInt8, a4: Double, a5: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + return hasher.finalize() +} + +public func swiftFunc39(a0: Int8, a1: UInt32, a2: Int, a3: Int16, a4: Int32, a5: UInt32, a6: Int, a7: Float, a8: Float, a9: Double, a10: UInt, a11: UInt16, a12: Int, a13: UInt64, a14: Int16, a15: Float, a16: Int64, a17: Int16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + return hasher.finalize() +} + +public func swiftFunc40(a0: UInt8, a1: UInt32, a2: Int64, a3: UInt16, a4: Double, a5: UInt32, a6: UInt64, a7: UInt32, a8: UInt32, a9: Int64, a10: UInt, a11: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + return hasher.finalize() +} + +public func swiftFunc41(a0: UInt64, a1: Int16, a2: Int, a3: Float, a4: Int8, a5: UInt32, a6: Int, a7: Int16, a8: UInt64, a9: Int8, a10: Float, a11: UInt, a12: UInt, a13: Int32, a14: Double, a15: Int64, a16: UInt8, a17: Float, a18: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + return hasher.finalize() +} + +public func swiftFunc42(a0: Int64, a1: UInt16, a2: Int, a3: UInt64, a4: Int) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + return hasher.finalize() +} + +public func swiftFunc43(a0: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + return hasher.finalize() +} + +public func swiftFunc44(a0: Double, a1: Int16, a2: Int64, a3: UInt32, a4: Int16, a5: Int16, a6: UInt64, a7: UInt32, a8: UInt32, a9: Int64, a10: UInt16, a11: UInt32, a12: Int16, a13: Int8, a14: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc45(a0: UInt8, a1: UInt8, a2: UInt64, a3: Int16, a4: Float, a5: Int16, a6: Int8, a7: UInt8, a8: Int32, a9: Int64, a10: Int16, a11: UInt, a12: Int16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + return hasher.finalize() +} + +public func swiftFunc46(a0: UInt64, a1: Int8, a2: Int8, a3: Int32, a4: Int16, a5: Int64, a6: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + return hasher.finalize() +} + +public func swiftFunc47(a0: UInt64, a1: UInt64, a2: UInt16, a3: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + return hasher.finalize() +} + +public func swiftFunc48(a0: UInt, a1: Int16, a2: Int, a3: Float, a4: Int8, a5: UInt64, a6: Int64, a7: Int8, a8: UInt8, a9: Int8, a10: Int8, a11: UInt64, a12: UInt32, a13: Int, a14: Float, a15: Int32, a16: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + return hasher.finalize() +} + +public func swiftFunc49(a0: UInt16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + return hasher.finalize() +} + +public func swiftFunc50(a0: Int64, a1: UInt16, a2: Int64, a3: UInt8, a4: Float, a5: Double, a6: Int16, a7: UInt32, a8: Int32, a9: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + return hasher.finalize() +} + +public func swiftFunc51(a0: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + return hasher.finalize() +} + +public func swiftFunc52(a0: UInt16, a1: UInt, a2: Int16, a3: Int32, a4: UInt16, a5: Int, a6: Int16, a7: UInt64, a8: Int, a9: Int16, a10: Int, a11: Double, a12: UInt16, a13: UInt8, a14: Int64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc53(a0: UInt64, a1: Int, a2: UInt64, a3: Double, a4: UInt64, a5: Int8, a6: Int64, a7: Float, a8: UInt8, a9: Int, a10: Int16, a11: UInt8, a12: UInt64, a13: Float, a14: UInt64, a15: Int8, a16: Int64, a17: UInt, a18: Int, a19: Float, a20: UInt8, a21: Int, a22: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + hasher.combine(a21); + hasher.combine(a22); + return hasher.finalize() +} + +public func swiftFunc54(a0: Int16, a1: UInt16, a2: Int64, a3: Int16, a4: Int64, a5: UInt8, a6: Int8, a7: Int32, a8: Float, a9: UInt64, a10: UInt16, a11: UInt32, a12: Int8, a13: UInt64, a14: UInt64, a15: Int32, a16: UInt32, a17: Int64, a18: UInt64, a19: UInt8, a20: UInt64, a21: UInt64, a22: Int, a23: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + hasher.combine(a21); + hasher.combine(a22); + hasher.combine(a23); + return hasher.finalize() +} + +public func swiftFunc55(a0: UInt64, a1: Int64, a2: UInt8, a3: UInt8, a4: UInt16, a5: Int64, a6: UInt64, a7: UInt64, a8: UInt64, a9: UInt16, a10: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + return hasher.finalize() +} + +public func swiftFunc56(a0: UInt, a1: Int32, a2: Double, a3: UInt64, a4: Float, a5: UInt32, a6: Int, a7: Int16, a8: UInt, a9: Double, a10: UInt32, a11: Int32, a12: UInt16, a13: Int8, a14: Int, a15: Int8, a16: UInt32, a17: Int8, a18: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + return hasher.finalize() +} + +public func swiftFunc57(a0: Int16, a1: Float, a2: UInt16, a3: Int, a4: UInt32, a5: Float, a6: Int8, a7: Int32, a8: UInt64, a9: Double, a10: Int64, a11: UInt, a12: UInt8, a13: UInt16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + return hasher.finalize() +} + +public func swiftFunc58(a0: Int, a1: Float, a2: UInt32, a3: Double, a4: UInt, a5: Int, a6: Float, a7: Int16, a8: Float, a9: UInt64, a10: Int8, a11: Float, a12: Int32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + return hasher.finalize() +} + +public func swiftFunc59(a0: UInt16, a1: UInt, a2: UInt16, a3: UInt, a4: UInt32, a5: UInt8, a6: Int16, a7: UInt64, a8: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + return hasher.finalize() +} + +public func swiftFunc60(a0: Double, a1: Int64, a2: UInt16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + return hasher.finalize() +} + +public func swiftFunc61(a0: Int8, a1: UInt8, a2: UInt8, a3: UInt64, a4: Int, a5: UInt32, a6: Int, a7: Int16, a8: Double, a9: Int8, a10: Int32, a11: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + return hasher.finalize() +} + +public func swiftFunc62(a0: UInt8, a1: UInt32, a2: Int16, a3: UInt8, a4: Int, a5: Float, a6: Double, a7: Int8, a8: UInt64, a9: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + return hasher.finalize() +} + +public func swiftFunc63(a0: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + return hasher.finalize() +} + +public func swiftFunc64(a0: Int16, a1: Int8, a2: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + return hasher.finalize() +} + +public func swiftFunc65(a0: Double, a1: UInt32, a2: Int32, a3: Int32, a4: UInt, a5: Int32, a6: Int8, a7: Int32, a8: UInt64, a9: UInt32, a10: Int32, a11: Int16, a12: Int8, a13: Int32, a14: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc66(a0: UInt, a1: UInt32, a2: UInt, a3: UInt16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + return hasher.finalize() +} + +public func swiftFunc67(a0: Double, a1: UInt16, a2: UInt32, a3: Int16, a4: Int32, a5: UInt32, a6: UInt8, a7: Double, a8: Double, a9: Int32, a10: UInt64, a11: Int32, a12: Int32, a13: Int16, a14: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + return hasher.finalize() +} + +public func swiftFunc68(a0: Double, a1: Int32, a2: Int32, a3: Int, a4: UInt) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + return hasher.finalize() +} + +public func swiftFunc69(a0: UInt, a1: UInt16, a2: Float, a3: UInt16, a4: Int64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + return hasher.finalize() +} + +public func swiftFunc70(a0: UInt32, a1: Double, a2: UInt8, a3: UInt, a4: Int16, a5: Int, a6: Double, a7: Int) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + return hasher.finalize() +} + +public func swiftFunc71(a0: UInt, a1: UInt64, a2: UInt32, a3: UInt32, a4: Int64, a5: Float, a6: Int16, a7: UInt8, a8: Double, a9: Float, a10: Int, a11: Int, a12: Double, a13: Int8, a14: Int16, a15: UInt32, a16: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + return hasher.finalize() +} + +public func swiftFunc72(a0: UInt64, a1: UInt8, a2: Int, a3: Int64, a4: UInt64, a5: Int16, a6: Int8, a7: Int8, a8: Double, a9: Float, a10: UInt16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + return hasher.finalize() +} + +public func swiftFunc73(a0: Int16, a1: Int32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + return hasher.finalize() +} + +public func swiftFunc74(a0: Int64, a1: Float, a2: UInt16, a3: UInt32, a4: Int32, a5: UInt32, a6: Int32, a7: UInt64, a8: UInt, a9: Double, a10: UInt64, a11: Int32, a12: Int16, a13: UInt32, a14: UInt64, a15: Int16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + return hasher.finalize() +} + +public func swiftFunc75(a0: UInt32, a1: UInt16, a2: Int8, a3: UInt8, a4: UInt16, a5: UInt32, a6: Double, a7: Int32, a8: Int64, a9: Int8, a10: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + return hasher.finalize() +} + +public func swiftFunc76(a0: Double, a1: Float, a2: UInt8, a3: UInt32, a4: Int32, a5: Int64, a6: Int16, a7: UInt16, a8: Int, a9: Int8, a10: UInt32, a11: Int64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + return hasher.finalize() +} + +public func swiftFunc77(a0: Double, a1: Int64, a2: Double, a3: Float, a4: Double, a5: Int64, a6: Int8, a7: UInt8, a8: Int8, a9: Int16, a10: UInt32, a11: UInt, a12: Int, a13: Float, a14: Int8, a15: UInt16, a16: Int16, a17: Double) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + return hasher.finalize() +} + +public func swiftFunc78(a0: Int64, a1: Int16, a2: UInt, a3: Int, a4: Int16, a5: UInt16, a6: Float, a7: Int8, a8: Int64, a9: UInt16, a10: Int32, a11: UInt8, a12: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + return hasher.finalize() +} + +public func swiftFunc79(a0: Float, a1: UInt32, a2: Int8, a3: Int, a4: Int64, a5: UInt8, a6: UInt32, a7: UInt32, a8: Float, a9: UInt32, a10: UInt8, a11: UInt64, a12: UInt16, a13: Int16, a14: UInt16, a15: UInt, a16: Double, a17: UInt64, a18: Int16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + return hasher.finalize() +} + +public func swiftFunc80(a0: Double, a1: Int32, a2: UInt64, a3: Int32, a4: UInt32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + return hasher.finalize() +} + +public func swiftFunc81(a0: Int, a1: Int8, a2: UInt32, a3: Double, a4: UInt64, a5: UInt64, a6: Float, a7: Int32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + return hasher.finalize() +} + +public func swiftFunc82(a0: UInt, a1: Double, a2: UInt16, a3: UInt64, a4: Int64, a5: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + return hasher.finalize() +} + +public func swiftFunc83(a0: Int32, a1: Int64, a2: Int64, a3: UInt8, a4: Double, a5: UInt16, a6: UInt16, a7: Int32, a8: UInt16, a9: UInt16, a10: Int16, a11: UInt32, a12: UInt64, a13: Int64, a14: Double, a15: UInt64, a16: Int32) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + return hasher.finalize() +} + +public func swiftFunc84(a0: Int64, a1: Int64, a2: Int, a3: Double, a4: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + return hasher.finalize() +} + +public func swiftFunc85(a0: Double, a1: Int8, a2: UInt, a3: UInt8, a4: UInt, a5: Int32, a6: Double, a7: Float, a8: Int32, a9: Int16, a10: Double, a11: Int32, a12: Float, a13: UInt, a14: Int16, a15: Int64, a16: UInt16, a17: Int16, a18: Int16, a19: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + return hasher.finalize() +} + +public func swiftFunc86(a0: UInt, a1: UInt16, a2: UInt64, a3: Int8, a4: Int8, a5: Int16, a6: UInt16, a7: Double, a8: Int16, a9: UInt16, a10: Int64, a11: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + return hasher.finalize() +} + +public func swiftFunc87(a0: UInt16, a1: UInt64, a2: Int64, a3: Int, a4: Int8, a5: Int16, a6: UInt32, a7: Int64, a8: Int16, a9: Int64, a10: Int64, a11: UInt8, a12: Float, a13: Int8, a14: Float, a15: Double, a16: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + return hasher.finalize() +} + +public func swiftFunc88(a0: UInt16, a1: UInt32, a2: Int16, a3: UInt64, a4: UInt16, a5: Int16, a6: Int16, a7: Double, a8: UInt, a9: Int32, a10: Float, a11: UInt, a12: UInt16, a13: UInt8, a14: UInt64, a15: Int8, a16: UInt8, a17: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + return hasher.finalize() +} + +public func swiftFunc89(a0: UInt8, a1: Int, a2: Int, a3: UInt8, a4: Int, a5: Float, a6: UInt, a7: Int16, a8: UInt16, a9: Int16, a10: Int, a11: UInt64, a12: Double, a13: Int64, a14: Double, a15: UInt64, a16: UInt64, a17: Int32, a18: UInt64, a19: UInt, a20: UInt, a21: UInt32, a22: Int16, a23: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + hasher.combine(a21); + hasher.combine(a22); + hasher.combine(a23); + return hasher.finalize() +} + +public func swiftFunc90(a0: UInt8, a1: Int8, a2: UInt64, a3: Float, a4: UInt32, a5: UInt32, a6: UInt16, a7: Int16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + return hasher.finalize() +} + +public func swiftFunc91(a0: Int16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + return hasher.finalize() +} + +public func swiftFunc92(a0: UInt16, a1: Int8, a2: Int16, a3: Double, a4: Int64, a5: Int, a6: UInt32, a7: UInt32, a8: Int, a9: UInt16, a10: Float, a11: UInt16, a12: UInt32, a13: UInt32, a14: Int, a15: Float) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + return hasher.finalize() +} + +public func swiftFunc93(a0: Int64, a1: UInt64, a2: UInt64, a3: UInt64, a4: UInt64, a5: Int8, a6: UInt8, a7: UInt16, a8: Int16, a9: Int32, a10: Float, a11: UInt16, a12: Int64, a13: Int64, a14: Double, a15: Int8, a16: Int16, a17: Int8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + return hasher.finalize() +} + +public func swiftFunc94(a0: UInt, a1: Float, a2: UInt32, a3: UInt, a4: Int, a5: UInt8, a6: UInt, a7: UInt32, a8: UInt16, a9: UInt8, a10: UInt, a11: UInt, a12: UInt32, a13: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + return hasher.finalize() +} + +public func swiftFunc95(a0: Float, a1: Int8, a2: Int64, a3: Float, a4: UInt64, a5: Int, a6: UInt32, a7: Int16, a8: UInt, a9: UInt16, a10: UInt64, a11: UInt, a12: UInt16, a13: UInt, a14: Double, a15: Int64, a16: Int64, a17: UInt8, a18: Int64, a19: UInt64, a20: Float, a21: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + hasher.combine(a17); + hasher.combine(a18); + hasher.combine(a19); + hasher.combine(a20); + hasher.combine(a21); + return hasher.finalize() +} + +public func swiftFunc96(a0: UInt64, a1: Int16, a2: UInt32, a3: Int64, a4: Float, a5: Int, a6: Int8, a7: Int8, a8: Int8, a9: UInt64, a10: UInt8, a11: UInt16, a12: UInt64, a13: UInt32, a14: Int64, a15: Int32, a16: UInt8) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + hasher.combine(a16); + return hasher.finalize() +} + +public func swiftFunc97(a0: UInt16, a1: UInt8, a2: UInt8, a3: Int8, a4: Int64, a5: UInt8, a6: UInt16, a7: UInt32, a8: UInt) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + return hasher.finalize() +} + +public func swiftFunc98(a0: UInt16, a1: Int8, a2: Double, a3: Int, a4: UInt, a5: UInt8, a6: UInt32, a7: UInt8, a8: UInt, a9: UInt16, a10: Float, a11: Int8, a12: Double, a13: Int32, a14: UInt16, a15: Int16) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + hasher.combine(a3); + hasher.combine(a4); + hasher.combine(a5); + hasher.combine(a6); + hasher.combine(a7); + hasher.combine(a8); + hasher.combine(a9); + hasher.combine(a10); + hasher.combine(a11); + hasher.combine(a12); + hasher.combine(a13); + hasher.combine(a14); + hasher.combine(a15); + return hasher.finalize() +} + +public func swiftFunc99(a0: UInt8, a1: UInt, a2: UInt64) -> Int { + var hasher = HasherFNV1a() + hasher.combine(a0); + hasher.combine(a1); + hasher.combine(a2); + return hasher.finalize() +} diff --git a/src/SwiftBindings/tests/SmokeTests.cs b/src/SwiftBindings/tests/SmokeTests.cs deleted file mode 100644 index db7c93457129..000000000000 --- a/src/SwiftBindings/tests/SmokeTests.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using Xunit; - -namespace SwiftBindings.Tests -{ - public class MyClassTests - { - [Fact] - public void Test1() - { - Assert.True(MyClass.ReturnTrue); - } - } -} diff --git a/src/SwiftBindings/tests/SwiftBindings.Tests.csproj b/src/SwiftBindings/tests/SwiftBindings.Tests.csproj index b09cc9165c4c..936b41f4f89c 100644 --- a/src/SwiftBindings/tests/SwiftBindings.Tests.csproj +++ b/src/SwiftBindings/tests/SwiftBindings.Tests.csproj @@ -1,9 +1,20 @@ net8.0 + enable + disable + false + true + cd $(OutputPath)$(TargetFramework) && cmake $(MSBuildThisFileDirectory) && make - + - + + + + + + + diff --git a/src/SwiftBindings/tests/TestsHelper.cs b/src/SwiftBindings/tests/TestsHelper.cs new file mode 100644 index 000000000000..80546053798f --- /dev/null +++ b/src/SwiftBindings/tests/TestsHelper.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.Loader; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Emit; + +namespace SwiftBindings.Tests +{ + public static class TestsHelper + { + private static int uniqueId = 0; + public static object CompileAndExecute(string filePath, string sourceCode, string typeName, string methodName) + { + string fileSourceCode = File.ReadAllText(filePath); + var sourceCodes = new[] { fileSourceCode, sourceCode }; + return CompileAndExecute(sourceCodes, typeName, methodName); + } + + private static object CompileAndExecute(string[] sourceCodes, string typeName, string methodName) + { + var options = new CSharpCompilationOptions(OutputKind.ConsoleApplication); + var syntaxTrees = sourceCodes.Select(code => CSharpSyntaxTree.ParseText(code)).ToArray(); + var systemRuntimeAssemblyPath = Assembly.Load("System.Runtime").Location; + + var references = new[] + { + MetadataReference.CreateFromFile(typeof(object).Assembly.Location), + MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), + MetadataReference.CreateFromFile(systemRuntimeAssemblyPath), + }; + + + var compilation = CSharpCompilation.Create($"CompiledAssembly{uniqueId}", + syntaxTrees: syntaxTrees, + references: references, + options: options); + + string assemblyPath = Path.Combine(Path.GetTempPath(), $"CompiledAssembly{uniqueId++}.dll"); + using (var stream = new FileStream(assemblyPath, FileMode.Create)) + { + EmitResult emitResult = compilation.Emit(stream); + + if (!emitResult.Success) + { + string errorMessage = "Compilation failed:"; + foreach (var diagnostic in emitResult.Diagnostics) + { + errorMessage += $"\n{diagnostic}"; + } + throw new InvalidOperationException(errorMessage); + } + } + + Assembly compiledAssembly = Assembly.LoadFile(assemblyPath); + Type targetType = compiledAssembly.GetType("Test.MainClass"); + MethodInfo customMethod = targetType.GetMethod(methodName); + return customMethod.Invoke(null, new object[] { }); + } + } +} \ No newline at end of file diff --git a/src/SwiftReflector/src/Enums.cs b/src/SwiftReflector/src/Enums.cs new file mode 100644 index 000000000000..7af4cc480e45 --- /dev/null +++ b/src/SwiftReflector/src/Enums.cs @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SwiftReflector +{ + public enum CoreCompoundType + { + ModuleName, + Function, + Class, + Struct, + Array, + Scalar, + Tuple, + BoundGeneric, + MetaClass, + LazyCache, + DirectMetadata, + NominalTypeDescriptor, + Variable, + Thunk, + ProtocolList, + ProtocolTypeDescriptor, + UnboundGeneric, + GenericReference, + FieldOffset, + ArgumentInitializer, + UnsafeMutableAddressor, + ProtocolConformanceDescriptor, + MethodDescriptor, + ModuleDescriptor, + PropertyDescriptor, + MetadataDescriptor, + ProtocolRequirementsBaseDescriptor, + BaseConformanceDescriptor, + AssociatedTypeDescriptor, + MetadataOffset, + MethodLookupFunction, + } + + public enum CoreBuiltInType + { + Int, + UInt, + Double, + Float, + Bool, + } + + public enum EntityType + { + None, + Class, + Struct, + Enum, + TrivialEnum, + Scalar, + Protocol, + Tuple, + Closure, + ProtocolList, + DynamicSelf, + } + + public enum MemberNesting + { + Class, + Struct, + Enum, + Protocol, + } + + public enum MemberType + { + Function, + UncurriedFunction, + Allocator, + Constructor, + Destructor, + Deallocator, + Getter, + Setter, + Materializer, + ExplicitClosure, + Addressor, + CFunction, + Initializer, + } + + public enum PropertyType + { + Getter, + Setter, + Materializer, + DidSet, + WillSet, + ModifyAccessor, + } + + public enum AddressorType + { + OwningMutable, + NativeOwningMutable, + NativePinningMutable, + UnsafeMutable, + Owning, + NativeOwning, + NativePinning, + Unsafe, + } + + public enum InitializerType + { + Variable, + } + + public enum ThunkType + { + Reabstraction, + ReabstractionHelper, + ProtocolWitness, + Curry, + } + + public enum OperatorType + { + None, + Prefix, + Postfix, + Infix, + Unknown, + } + + public enum WitnessType + { + Class, + Value, + Protocol, + ProtocolAccessor, + } + + public enum PlatformName + { + None, // desktop managed executable + macOS, // Xamarin.Mac app + iOS, + watchOS, + tvOS, + } + + public enum SwiftTypeAttribute + { + ObjC, + NonObjC, + Dynamic, + ImplFunction, + DirectMethodReference, + } + + public enum ReflectionStrategy + { + None, + [Obsolete("Compiler reflection is no longer supported.", true)] + Compiler, + Parser, + } + + public enum TargetCpu + { + Arm64, + Armv7, + Armv7s, + Arm7vk, + Arm64e, + Arm64_32, + I386, + X86_64, + } + + public enum TargetManufacturer + { + Apple, + } + + public enum TargetEnvironment + { + Device, + Simulator, + } + + public enum TargetRepresentationKind + { + None, + Library, + Framework, + XCFramework, + } +} + diff --git a/src/SwiftReflector/src/ErrorHandling.cs b/src/SwiftReflector/src/ErrorHandling.cs new file mode 100644 index 000000000000..1b3bb494578c --- /dev/null +++ b/src/SwiftReflector/src/ErrorHandling.cs @@ -0,0 +1,119 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.ExceptionServices; + +namespace SwiftReflector +{ + public class ErrorHandling + { + object messagesLock = new object(); + List messages; + + public ErrorHandling() + { + messages = new List(); + SkippedTypes = new List(); + SkippedFunctions = new List(); + } + + public IEnumerable Messages + { + get { return messages; } + } + + public IEnumerable Errors + { + get { return messages.Where((v) => !v.IsWarning); } + } + + public IEnumerable Warnings + { + get { return messages.Where((v) => v.IsWarning); } + } + + public List SkippedTypes { get; private set; } + public List SkippedFunctions { get; private set; } + + public void Add(ErrorHandling eh) + { + lock (messagesLock) + { + lock (eh.messagesLock) + { + messages.AddRange(eh.messages); + } + } + } + + public void Add(params ReflectorError[] errors) + { + lock (messagesLock) + { + messages.AddRange(errors); + } + } + + public void Add(Exception exception) + { + lock (messagesLock) + { + messages.Add(new ReflectorError(exception)); + } + } + + public bool AnyMessages + { + get + { + lock (messagesLock) + { + return messages.Count > 0; + } + } + } + + public bool AnyErrors + { + get + { + lock (messagesLock) + { + return messages.Any((v) => !v.IsWarning); + } + } + } + + public int WarningCount + { + get + { + lock (messagesLock) + { + return messages.Count((v) => v.IsWarning); + } + } + } + + public int ErrorCount + { + get + { + lock (messagesLock) + { + return messages.Count((v) => !v.IsWarning); + } + } + } + + public int Show(int verbosity) + { + // ErrorHelper.Verbosity = verbosity; + // return ErrorHelper.Show (messages.Select ((v) => v.Exception)); + return verbosity; + } + } +} diff --git a/src/SwiftReflector/src/ExceptionTools/ErrorHelper.cs b/src/SwiftReflector/src/ExceptionTools/ErrorHelper.cs new file mode 100644 index 000000000000..61c57765874e --- /dev/null +++ b/src/SwiftReflector/src/ExceptionTools/ErrorHelper.cs @@ -0,0 +1,191 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using ProductException = SwiftReflector.ExceptionTools.RuntimeException; + +namespace SwiftReflector.ExceptionTools +{ + static class ErrorHelper + { + public enum WarningLevel + { + Error = -1, + Warning = 0, + Disable = 1, + } + public const string Prefix = "BT"; + static Dictionary warning_levels; + public static int Verbosity { get; set; } + + public static WarningLevel GetWarningLevel(int code) + { + WarningLevel level; + + if (warning_levels == null) + return WarningLevel.Warning; + + // code -1: all codes + if (warning_levels.TryGetValue(-1, out level)) + return level; + + if (warning_levels.TryGetValue(code, out level)) + return level; + + return WarningLevel.Warning; + } + + public static void SetWarningLevel(WarningLevel level, int? code = null /* if null, apply to all warnings */) + { + if (warning_levels == null) + warning_levels = new Dictionary(); + if (code.HasValue) + { + warning_levels[code.Value] = level; + } + else + { + warning_levels[-1] = level; // code -1: all codes. + } + } + + public static ProductException CreateError(int code, string message, params object[] args) + { + return new ProductException(code, true, message, args); + } + + public static ProductException CreateError(int code, Exception innerException, string message, params object[] args) + { + return new ProductException(code, true, innerException, message, args); + } + + public static ProductException CreateWarning(int code, string message, params object[] args) + { + return new ProductException(code, false, message, args); + } + + public static ProductException CreateWarning(int code, Exception innerException, string message, params object[] args) + { + return new ProductException(code, false, innerException, message, args); + } + + public static void Error(int code, Exception innerException, string message, params object[] args) + { + throw new ProductException(code, true, innerException, message, args); + } + + public static void Error(int code, string message, params object[] args) + { + throw new ProductException(code, true, message, args); + } + + public static void Warning(int code, string message, params object[] args) + { + Show(new ProductException(code, false, message, args)); + } + + public static void Warning(int code, Exception innerException, string message, params object[] args) + { + Show(new ProductException(code, false, innerException, message, args)); + } + + public static int Show(IEnumerable list) + { + List exceptions = new List(); + bool error = false; + + foreach (var e in list) + CollectExceptions(e, exceptions); + + foreach (var ex in exceptions) + error |= ShowInternal(ex); + + return error ? 1 : 0; + } + + static public int Show(Exception e) + { + List exceptions = new List(); + bool error = false; + + CollectExceptions(e, exceptions); + + foreach (var ex in exceptions) + error |= ShowInternal(ex); + + return error ? 1 : 0; + } + + static void Exit(int exitCode) + { + Environment.Exit(exitCode); + } + + static void CollectExceptions(Exception ex, List exceptions) + { + AggregateException ae = ex as AggregateException; + + if (ae != null && ae.InnerExceptions.Count > 0) + { + foreach (var ie in ae.InnerExceptions) + CollectExceptions(ie, exceptions); + } + else + { + exceptions.Add(ex); + } + } + + static bool ShowInternal(Exception e) + { + ProductException mte = (e as ProductException); + bool error = true; + + if (mte != null) + { + error = mte.Error; + + if (!error && GetWarningLevel(mte.Code) == WarningLevel.Disable) + return false; // This is an ignored warning. + + Console.Error.WriteLine(mte.ToString()); + + if (Verbosity > 1) + ShowInner(e); + + if (Verbosity > 2 && !string.IsNullOrEmpty(e.StackTrace)) + Console.Error.WriteLine(e.StackTrace); + } + else + { + Console.Error.WriteLine(e.ToString()); + if (Verbosity > 1) + ShowInner(e); + if (Verbosity > 2 && !string.IsNullOrEmpty(e.StackTrace)) + Console.Error.WriteLine(e.StackTrace); + } + + return error; + } + + static void ShowInner(Exception e) + { + Exception ie = e.InnerException; + if (ie == null) + return; + + if (Verbosity > 3) + { + Console.Error.WriteLine("--- inner exception"); + Console.Error.WriteLine(ie); + Console.Error.WriteLine("---"); + } + else + { + Console.Error.WriteLine("\t{0}", ie.Message); + } + ShowInner(ie); + } + } +} diff --git a/src/SwiftReflector/src/ExceptionTools/RuntimeException.cs b/src/SwiftReflector/src/ExceptionTools/RuntimeException.cs new file mode 100644 index 000000000000..a60ff34997a1 --- /dev/null +++ b/src/SwiftReflector/src/ExceptionTools/RuntimeException.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SwiftReflector.ExceptionTools +{ + + public class RuntimeException : Exception + { + // Store the stack trace when this exception was created, and return + // it if the base class doesn't have a stack trace (which would happen + // if this exception was never thrown). + string stack_trace; + + public RuntimeException(string message, params object[] args) + : base(string.Format(message, args)) + { + stack_trace = new System.Diagnostics.StackTrace(true).ToString(); + } + + public RuntimeException(int code, string message, params object[] args) : + this(code, false, message, args) + { + } + + public RuntimeException(int code, bool error, string message, params object[] args) : + this(code, error, null, message, args) + { + } + + public RuntimeException(int code, bool error, Exception innerException, string message, params object[] args) : + base(String.Format(message, args), innerException) + { + stack_trace = new System.Diagnostics.StackTrace(true).ToString(); + Code = code; + Error = error; + } + + public int Code { get; private set; } + + public bool Error { get; private set; } + + // http://blogs.msdn.com/b/msbuild/archive/2006/11/03/msbuild-visual-studio-aware-error-messages-and-message-formats.aspx + public override string ToString() + { + return String.Format("{0} {1:0000}: {2}", Error ? "error" : "warning", Code, Message); + } + + public override string StackTrace + { + get + { + var thrownTrace = base.StackTrace; + if (string.IsNullOrEmpty(thrownTrace)) + return stack_trace; + return thrownTrace; + } + } + } +} diff --git a/src/SwiftReflector/src/Extensions.cs b/src/SwiftReflector/src/Extensions.cs new file mode 100644 index 000000000000..1f1e852a1e06 --- /dev/null +++ b/src/SwiftReflector/src/Extensions.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +// using Xamarin; +using System.Text; +using SyntaxDynamo; +using System.Collections; + +namespace SwiftReflector +{ + public static class Extensions + { + public static Tuple SplitModuleFromName(this string s) + { + int dotIndex = s.IndexOf('.'); + if (dotIndex < 0) + return new Tuple(null, s); + if (dotIndex == 0) + return new Tuple(null, s.Substring(1)); + return new Tuple(s.Substring(0, dotIndex), s.Substring(dotIndex + 1)); + } + + public static string ModuleFromName(this string s) + { + return s.SplitModuleFromName().Item1; + } + + public static string NameWithoutModule(this string s) + { + return s.SplitModuleFromName().Item2; + } + + public static string InterleaveStrings(this IEnumerable elements, string separator, bool includeSepFirst = false) + { + StringBuilder sb = new StringBuilder(); + foreach (string s in elements.Interleave(separator, includeSepFirst)) + sb.Append(s); + return sb.ToString(); + } + + public static string InterleaveCommas(this IEnumerable elements) + { + return elements.InterleaveStrings(", "); + } + } +} + diff --git a/src/SwiftReflector/src/Parser/ISwiftParser.cs b/src/SwiftReflector/src/Parser/ISwiftParser.cs new file mode 100644 index 000000000000..4a86efe948ba --- /dev/null +++ b/src/SwiftReflector/src/Parser/ISwiftParser.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SwiftReflector.SwiftXmlReflection; + +namespace SwiftReflector.Parser +{ + public interface ISwiftParser + { + public ModuleDeclaration GetModuleDeclaration(string filePath, ErrorHandling errors); + } +} \ No newline at end of file diff --git a/src/SwiftReflector/src/Parser/SwiftABIParser/SwiftABIParser.cs b/src/SwiftReflector/src/Parser/SwiftABIParser/SwiftABIParser.cs new file mode 100644 index 000000000000..a2dc0d3040ff --- /dev/null +++ b/src/SwiftReflector/src/Parser/SwiftABIParser/SwiftABIParser.cs @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using SwiftReflector.SwiftXmlReflection; + +namespace SwiftReflector.Parser +{ + public class ABIRootNode + { + [JsonProperty("ABIRoot")] + public RootNode ABIRoot { get; set; } + } + + public class RootNode + { + public string Kind { get; set; } + public string Name { get; set; } + public string PrintedName { get; set; } + public List Children { get; set; } + } + + public class Node + { + public string Kind { get; set; } + public string Name { get; set; } + public string MangledName { get; set; } + public string ModuleName { get; set; } + public string PrintedName { get; set; } + public List Children { get; set; } + } + + public class SwiftABIParser : ISwiftParser + { + public ModuleDeclaration GetModuleDeclaration(string filePath, ErrorHandling errors) + { + string jsonContent = File.ReadAllText(filePath); + var abiRoot = JsonConvert.DeserializeObject(jsonContent); + + var stack = new Stack(); + foreach (var child in abiRoot.ABIRoot.Children) + { + stack.Push(child); + } + + string moduleName = Path.GetFileNameWithoutExtension(filePath); + if (moduleName.EndsWith(".abi", StringComparison.OrdinalIgnoreCase)) + moduleName = moduleName.Substring(0, moduleName.Length - 4); + + ModuleDeclaration moduleDeclaration = new ModuleDeclaration(moduleName); + while (stack.Count > 0) + { + var node = stack.Pop(); + + switch (node.Kind) + { + case "Function": + var decl = CreateFunctionDecl(node); + decl.Module = moduleDeclaration; + moduleDeclaration.Declarations.Add(decl); + break; + default: + errors.Add(new NotImplementedException()); + break; + + } + + if (node.Children != null) + { + foreach (var child in node.Children) + { + stack.Push(child); + } + } + } + + return moduleDeclaration; + } + + public FunctionDeclaration CreateFunctionDecl(Node decl) + { + FunctionDeclaration functionDeclaration = new FunctionDeclaration(); + functionDeclaration.Name = decl.Name; + functionDeclaration.MangledName = decl.MangledName; + functionDeclaration.IsStatic = true; + + switch (decl.Children[0].Name) + { + case "Void": + functionDeclaration.ReturnTypeSpec = new TupleTypeSpec(); + break; + default: + functionDeclaration.ReturnTypeSpec = new NamedTypeSpec(decl.Children[0].PrintedName); + break; + } + + functionDeclaration.ParameterLists.Add(new List()); + var funcSignature = decl.PrintedName.Split("(")[1].Split(")")[0].Split(":", StringSplitOptions.RemoveEmptyEntries); + for (int i = 1; i < decl.Children.Count; i++) + { + var param = decl.Children[i]; + ParameterItem parameterItem = new ParameterItem(); + parameterItem.TypeSpec = new NamedTypeSpec(param.PrintedName); + if (funcSignature.Length > i - 1) + parameterItem.PublicName = funcSignature[i - 1]; + functionDeclaration.ParameterLists.FirstOrDefault().Add(parameterItem); + } + return functionDeclaration; + } + } +} \ No newline at end of file diff --git a/src/SwiftReflector/src/Parser/SwiftInterfaceParser/.gitkeep b/src/SwiftReflector/src/Parser/SwiftInterfaceParser/.gitkeep new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/src/SwiftReflector/src/ReflectorError.cs b/src/SwiftReflector/src/ReflectorError.cs new file mode 100644 index 000000000000..5b56fcb6708d --- /dev/null +++ b/src/SwiftReflector/src/ReflectorError.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using SwiftReflector.ExceptionTools; +using System.Linq; + +namespace SwiftReflector +{ + + // Range of error messages + // 0000 - total abject failure + // 0500 - should never, ever happen. Ever. (skipped case, argument null, argument out of range) + // 1000 - compiler error, generating C# + // 1500 - compiler error, C# trying to reference swift wrapper + // 2500 - importing types from C# bindings + // 2000 - wrapping error, wrapping swift code in C# callable wrappers + // 3000 - decomposition error, demangling swift symbols + // 4000 - error dropping swift symbols into inventory + // 5000 - error reflecting on swift module + // 6000 - error parsing TypeSpec + // 7000 - error mapping one type to another + + + public class ReflectorError + { + public const int kCantHappenBase = 500; + public const int kCompilerBase = 1000; + public const int kCompilerReferenceBase = 1500; + public const int kWrappingBase = 2000; + public const int kImportingBase = 2500; + public const int kDecomposeBase = 3000; + public const int kInventoryBase = 4000; + public const int kReflectionErrorBase = 5000; + public const int kTypeParseBase = 6000; + public const int kTypeMapBase = 7000; + + public ReflectorError(Exception e) + { + if (e is RuntimeException re) + { + Exception = re; + Error = re.Error; + } + else if (e is AggregateException ae && ae.InnerExceptions.All((v) => v is RuntimeException)) + { + Exception = ae; + // If any of the exceptions is an error, the whole collection is an error as well. + Error = ae.InnerExceptions.Cast().Any((v) => v.Error); + } + else + { + Exception = new RuntimeException(kCantHappenBase + 54, error: true, innerException: e, message: e.Message); + Error = true; + } + } + + public Exception Exception { get; private set; } + public bool Error { get; private set; } + + public bool IsWarning => !Error; + public string Message => Exception.Message; + } +} diff --git a/src/SwiftReflector/src/SwiftClassName.cs b/src/SwiftReflector/src/SwiftClassName.cs new file mode 100644 index 000000000000..7b61e530c182 --- /dev/null +++ b/src/SwiftReflector/src/SwiftClassName.cs @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SwiftRuntimeLibrary; + +namespace SwiftReflector +{ + public class SwiftClassName + { + public SwiftClassName(SwiftName module, IList nesting, IList nestingNames, OperatorType oper = OperatorType.None) + { + ArgumentNullException.ThrowIfNull(module, nameof(module)); + ArgumentNullException.ThrowIfNull(nesting, nameof(nesting)); + ArgumentNullException.ThrowIfNull(nestingNames, nameof(nestingNames)); + Module = module; + Nesting = nesting; + NestingNames = nestingNames; + Terminus = NestingNames.Count > 0 ? NestingNames[NestingNames.Count - 1] : null; + Operator = oper; + } + + public SwiftName Module { get; private set; } + public IList Nesting { get; private set; } + public IList NestingNames { get; private set; } + public SwiftName Terminus { get; private set; } + public OperatorType Operator { get; set; } + + public bool IsClass { get { return Nesting.Count > 0 && Nesting.Last() == MemberNesting.Class; } } + public bool IsStruct { get { return Nesting.Count > 0 && Nesting.Last() == MemberNesting.Struct; } } + public bool IsEnum { get { return Nesting.Count > 0 && Nesting.Last() == MemberNesting.Enum; } } + public bool IsOperator { get { return Operator != OperatorType.None; } } + public string ToFullyQualifiedName(bool includeModule = true) + { + var sb = new StringBuilder(); + if (includeModule) + sb.Append(Module.Name); + for (int i = 0; i < NestingNames.Count; i++) + { + if (includeModule || (!includeModule && i > 0)) + sb.Append('.'); + sb.Append(NestingNames[i].Name); + } + return sb.ToString(); + } + + public override int GetHashCode() + { + int hashCode = Module.GetHashCode(); + foreach (SwiftName name in NestingNames) + hashCode += name.GetHashCode(); + return hashCode; + } + + public override bool Equals(object obj) + { + var other = obj as SwiftClassName; + if (other == null) + { + return false; + } + if (other == this) + return true; + return Module.Equals(other.Module) && NamesAreEqual(other); + } + + public override string ToString() + { + return ToFullyQualifiedName(true); + } + + bool NamesAreEqual(SwiftClassName other) + { + if (NestingNames.Count != other.NestingNames.Count) + return false; + for (int i = 0; i < NestingNames.Count; i++) + { + if (!NestingNames[i].Equals(other.NestingNames[i])) + return false; + } + return true; + } + + } +} + diff --git a/src/SwiftReflector/src/SwiftName.cs b/src/SwiftReflector/src/SwiftName.cs new file mode 100644 index 000000000000..b22573bc855f --- /dev/null +++ b/src/SwiftReflector/src/SwiftName.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SwiftReflector +{ + public class SwiftName + { + public SwiftName(string name, bool isPunyCode) + { + if (name == null) + throw new ArgumentNullException("name"); + PunyName = name; + // Name = isPunyCode ? name.DePunyCode() : name; + Name = name; + } + + public string Name { get; private set; } + public string PunyName { get; private set; } + public bool HasPunyCode { get { return Name != PunyName; } } + + public override string ToString() + { + return HasPunyCode ? String.Format("{0} ({1})", Name, PunyName) : Name; + } + + static SwiftName emptyName = new SwiftName("", false); + public static SwiftName Empty { get { return emptyName; } } + + public override bool Equals(object obj) + { + var other = obj as SwiftName; + if (other == null) + return false; + return (PunyName == other.PunyName) && + (HasPunyCode ? Name == other.Name : true); + } + + public override int GetHashCode() + { + return PunyName.GetHashCode() + + (HasPunyCode ? Name.GetHashCode() : 0); + } + } +} + diff --git a/src/SwiftReflector/src/SwiftReflector.csproj b/src/SwiftReflector/src/SwiftReflector.csproj new file mode 100644 index 000000000000..c0f115ffda2a --- /dev/null +++ b/src/SwiftReflector/src/SwiftReflector.csproj @@ -0,0 +1,14 @@ + + + Library + net8.0 + enable + disable + true + + + + + + + diff --git a/src/SwiftReflector/src/SwiftType.cs b/src/SwiftReflector/src/SwiftType.cs new file mode 100644 index 000000000000..eba26743ef29 --- /dev/null +++ b/src/SwiftReflector/src/SwiftType.cs @@ -0,0 +1,330 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SwiftRuntimeLibrary; + +namespace SwiftReflector +{ + public class SwiftType + { + protected SwiftType(CoreCompoundType type, bool isReference, SwiftName name = null) + { + Type = type; + IsReference = isReference; + Name = name; + Attributes = new List(); + IsVariadic = false; + } + + public CoreCompoundType Type { get; private set; } + public SwiftName Name { get; private set; } + public bool IsReference { get; private set; } + public List Attributes { get; private set; } + public bool IsVariadic { get; set; } + + + public SwiftType ReferenceCloneOf() + { + if (IsReference) + return this; + var ty = MemberwiseClone() as SwiftType; + ty.IsReference = true; + return ty; + } + + public SwiftType NonReferenceCloneOf() + { + if (!IsReference) + return this; + var ty = MemberwiseClone() as SwiftType; + ty.IsReference = false; + return ty; + } + + public SwiftType RenamedCloneOf(SwiftName newName) + { + var ty = MemberwiseClone() as SwiftType; + ty.Name = newName; + return ty; + } + + public bool IsEmptyTuple + { + get + { + var tuple = this as SwiftTupleType; + return tuple == null ? false : tuple.IsEmpty; + } + } + public virtual bool IsClass { get { return false; } } + public virtual bool IsStruct { get { return false; } } + public virtual bool IsEnum { get { return false; } } + public virtual bool IsProtocol { get { return false; } } + + public bool HasAttribute(SwiftTypeAttribute attribute) + { + return Attributes.Any(attr => attr == attribute); + } + + [Obsolete("this is not supported in Swift 5")] + public bool HasObjCAttribute => HasAttribute(SwiftTypeAttribute.ObjC); + + public override int GetHashCode() + { + return Type.GetHashCode() + + (Name != null ? Name.GetHashCode() : 0); + } + + public override bool Equals(object obj) + { + var type = obj as SwiftType; + if (type == null) + return false; + if (type.Type != Type) + return false; + if (type.IsReference != IsReference) + return false; + if (type.IsVariadic != IsVariadic) + return false; + if (type.GetType() != this.GetType()) + return false; + // shouldn't do Name equality except in functions + return LLEquals(type); + } + + public virtual bool EqualsReferenceInvaraint(SwiftType type) + { + var a = ProjectAsNonReference(this); + var b = ProjectAsNonReference(type); + + if (b.Type != a.Type) + return false; + if (b.GetType() != a.GetType()) + return false; + // shouldn't do Name equality except in functions + return a.LLEquals(b); + } + + static SwiftType ProjectAsNonReference(SwiftType a) + { + if (a.IsReference) + { + return a.NonReferenceCloneOf(); + } + var bgt = a as SwiftBoundGenericType; + if (bgt != null && bgt.BoundTypes.Count == 1) + { + var baseType = bgt.BaseType as SwiftClassType; + if (baseType != null) + { + string name = baseType.ClassName.ToFullyQualifiedName(true); + if (name == "Swift.UnsafePointer" || name == "Swift.UnsafeMutablePointer") + return bgt.BoundTypes[0]; + } + } + return a; + } + + protected virtual bool LLEquals(SwiftType other) + { + return true; + } + + + public static bool IsStructScalar(SwiftType st) + { + if (st == null) + return false; + if (st is SwiftBuiltInType) + return true; + var ct = st as SwiftClassType; + if (ct == null) + return false; + return IsStructScalar(ct.ClassName.ToFullyQualifiedName()); + } + + public static bool IsStructScalar(string fullyQualifiedName) + { + switch (fullyQualifiedName) + { + case "Swift.Int64": + case "Swift.UInt64": + case "Swift.Int32": + case "Swift.UInt32": + case "Swift.Int16": + case "Swift.UInt16": + case "Swift.Int8": + case "Swift.UInt8": + case "Swift.Char": + case "CoreGraphics.CGFloat": + case "Swift.UnsafeRawPointer": + case "Swift.UnsafeMutableRawPointer": + case "Swift.OpaquePointer": + return true; + default: + return false; + } + } + } + + public class SwiftTupleType : SwiftType + { + public SwiftTupleType(bool isReference) + : this(null, isReference, null) + { + } + + public SwiftTupleType(IEnumerable contents, bool isReference, SwiftName name = null) + : base(CoreCompoundType.Tuple, isReference, name) + { + Contents = new List(); + if (contents != null) + Contents.AddRange(contents); + } + + public SwiftTupleType(bool isReference, SwiftName name, params SwiftType[] contents) + : this(contents, isReference, name) + { + } + + public List Contents { get; private set; } + public bool IsEmpty { get { return Contents.Count == 0; } } + static SwiftTupleType empty = new SwiftTupleType(null, false, null); + public static SwiftTupleType Empty { get { return empty; } } + + public bool HasNames() + { + return Contents.FirstOrDefault(st => st.Name != null) != null; + } + + protected override bool LLEquals(SwiftType other) + { + SwiftTupleType st = other as SwiftTupleType; + if (st == null) + return false; + return Contents.SequenceEqual(st.Contents); + } + + public SwiftType AllButFirst() + { + if (IsEmpty) + throw new ArgumentOutOfRangeException("tuple is empty"); + // seriously, this is what we want to do. + // If a function has one argument, it will be a the simple type. + // If a function has more than one argument, it will be a tuple. + if (Contents.Count == 2) + return Contents[1]; + return new SwiftTupleType(Contents.TakeWhile((st, i) => i > 0), IsReference, Name); + } + + public SwiftType AllButFirstN(int n) + { + if (IsEmpty) + throw new ArgumentOutOfRangeException("tuple is empty"); + // seriously, this is what we want to do. + // If a function has one argument, it will be a the simple type. + // If a function has more than one argument, it will be a tuple. + // So if we are returning the last element, we're returning an single not a tuple. + if (Contents.Count == n + 1) + return Contents[n]; + return new SwiftTupleType(Contents.Skip(n), IsReference, Name); + } + + public override string ToString() + { + var contents = Contents.Select(el => + { + var elname = el.Name != null ? el.Name.Name + ": " : ""; + return elname + el.ToString(); + }).InterleaveCommas(); + return $"({contents})"; + } + } + + public class SwiftBuiltInType : SwiftType + { + public SwiftBuiltInType(CoreBuiltInType scalarType, bool isReference, SwiftName name = null) + : base(CoreCompoundType.Scalar, isReference, name) + { + BuiltInType = scalarType; + } + + public CoreBuiltInType BuiltInType { get; private set; } + + protected override bool LLEquals(SwiftType other) + { + SwiftBuiltInType sb = other as SwiftBuiltInType; + return sb != null && BuiltInType == sb.BuiltInType; + } + public override string ToString() + { + var name = Name != null ? Name.Name + ": " : ""; + return name + BuiltInType.ToString(); + } + + } + + public class SwiftClassType : SwiftType + { + public SwiftClassType(SwiftClassName className, bool isReference, SwiftName name = null) + : base(CoreCompoundType.Class, isReference, name) + { + ClassName = className; + } + public SwiftClassName ClassName { get; private set; } + public override bool IsClass { get { return EntityKind == MemberNesting.Class; } } + public override bool IsStruct { get { return EntityKind == MemberNesting.Struct; } } + public override bool IsEnum { get { return EntityKind == MemberNesting.Enum; } } + public override bool IsProtocol { get { return EntityKind == MemberNesting.Protocol; } } + + public MemberNesting EntityKind { get { return ClassName.Nesting.Last(); } } + + protected override bool LLEquals(SwiftType other) + { + var sct = other as SwiftClassType; + return sct != null && ClassName.Equals(sct.ClassName); + } + + public override string ToString() + { + var name = Name != null ? Name.Name + ": " : ""; + return name + ClassName.ToFullyQualifiedName(); + } + } + + public class SwiftBoundGenericType : SwiftType + { + public SwiftBoundGenericType(SwiftType baseType, List boundTypes, bool isReference, SwiftName name = null) + : base(CoreCompoundType.BoundGeneric, isReference, name) + { + ArgumentNullException.ThrowIfNull(baseType, nameof(baseType)); + BaseType = baseType; + BoundTypes = new List(); + if (boundTypes != null) + BoundTypes.AddRange(boundTypes); + } + public SwiftType BaseType { get; private set; } + public List BoundTypes { get; private set; } + protected override bool LLEquals(SwiftType other) + { + var bgt = other as SwiftBoundGenericType; + return bgt != null && BaseType.Equals(bgt.BaseType) + && BoundTypes.SequenceEqual(bgt.BoundTypes); + } + + public override bool IsClass { get { return BaseType.IsClass; } } + public override bool IsEnum { get { return BaseType.IsEnum; } } + public override bool IsStruct { get { return BaseType.IsStruct; } } + public override string ToString() + { + var name = Name != null ? Name.Name + ": " : ""; + var genArgs = BoundTypes.Select(arg => arg.ToString()).InterleaveCommas(); + return $"{name}{BaseType.ToString()}<{genArgs}>"; + } + } + +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/AssociatedTypeDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/AssociatedTypeDeclaration.cs new file mode 100644 index 000000000000..8590efeb6add --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/AssociatedTypeDeclaration.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Xml.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class AssociatedTypeDeclaration + { + public AssociatedTypeDeclaration() + { + ConformingProtocols = new List(); + } + + public string Name { get; set; } + + public TypeSpec SuperClass { get; set; } + public TypeSpec DefaultType { get; set; } + public List ConformingProtocols { get; private set; } + + + public static AssociatedTypeDeclaration FromXElement(TypeAliasFolder folder, XElement elem) + { + var assocType = new AssociatedTypeDeclaration(); + assocType.Name = NameAttribute(elem); + + var superClassElem = elem.Element("superclass"); + if (superClassElem != null) + { + var superClassName = NameAttribute(superClassElem); + if (superClassName != null) + { + assocType.SuperClass = folder.FoldAlias(null, TypeSpecParser.Parse(superClassName)); + } + } + var defaultDefn = elem.Attribute("defaulttype"); + if (defaultDefn != null) + { + assocType.DefaultType = folder.FoldAlias(null, TypeSpecParser.Parse((string)defaultDefn)); + } + + if (elem.Element("conformingprotocols") != null) + { + var conforming = from conform in elem.Element("conformingprotocols").Elements() + select folder.FoldAlias(null, TypeSpecParser.Parse(NameAttribute(conform))) as NamedTypeSpec; + assocType.ConformingProtocols.AddRange(conforming); + } + + return assocType; + } + + public void GatherXObjects(List xobjects) + { + xobjects.Add(new XAttribute("name", Name)); + if (SuperClass != null) + xobjects.Add(new XElement("superclass", new XElement("superclass", new XAttribute("name", SuperClass.ToString())))); + if (DefaultType != null) + xobjects.Add(new XAttribute("defaulttype", DefaultType.ToString())); + var conforming = new List(); + foreach (var spec in ConformingProtocols) + { + conforming.Add(new XElement("conformingprotocol", new XAttribute("name", spec.ToString()))); + } + xobjects.Add(new XElement("conformingprotocols", conforming.ToArray())); + } + + static string NameAttribute(XElement elem) + { + return (string)elem.Attribute("name"); + } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/AttributeDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/AttributeDeclaration.cs new file mode 100644 index 000000000000..c106d3d1e5a3 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/AttributeDeclaration.cs @@ -0,0 +1,165 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Xml.Linq; +using SyntaxDynamo; +using System.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class AttributeDeclaration + { + public AttributeDeclaration(string typeName) + { + ArgumentNullException.ThrowIfNull(typeName, nameof(typeName)); + Name = typeName; + Parameters = new List(); + } + + public AttributeDeclaration(AttributeDeclaration other) + : this(other.Name) + { + foreach (var parameter in other.Parameters) + Parameters.Add(DuplicateOf(parameter)); + } + + public static AttributeDeclaration FromXElement(XElement elem) + { + var decl = new AttributeDeclaration(elem.Attribute("name").Value); + var parameters = elem.Element("attributeparameterlist"); + if (parameters == null) + return decl; + FromAttributeParameterList(parameters, decl.Parameters); + return decl; + } + + internal static void FromAttributeParameterList(XElement parameters, List outlist) + { + foreach (var parameterElem in parameters.Elements("attributeparameter")) + { + var parameter = AttributeParameter.FromXElement(parameterElem); + outlist.Add(parameter); + } + } + + public static AttributeParameter DuplicateOf(AttributeParameter other) + { + switch (other.Kind) + { + case AttributeParameterKind.Label: + return new AttributeParameterLabel((AttributeParameterLabel)other); + case AttributeParameterKind.Literal: + return new AttributeParameterLiteral((AttributeParameterLiteral)other); + case AttributeParameterKind.Sublist: + return new AttributeParameterSublist((AttributeParameterSublist)other); + case AttributeParameterKind.Unknown: + return new AttributeParameter(); + default: + throw new ArgumentOutOfRangeException(nameof(other), other.Kind.ToString()); + } + } + + public NamedTypeSpec AttributeType { get; private set; } + public string Name + { + get + { + return AttributeType.ToString(true); + } + private set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + var ts = TypeSpecParser.Parse(value); + if (ts is NamedTypeSpec named) + AttributeType = named; + else + throw new ArgumentOutOfRangeException($"TypeSpec for {value} is a {ts.Kind} and not a named type spec"); + } + } + public List Parameters { get; private set; } + } + + public class AttributeParameter + { + public static AttributeParameter FromXElement(XElement elem) + { + switch (elem.Attribute("kind").Value) + { + case "Label": + return new AttributeParameterLabel(elem.Attribute("Value").Value); + case "Literal": + return new AttributeParameterLiteral(elem.Attribute("Value").Value); + case "Sublist": + return AttributeParameterSublist.SublistFromXElement(elem); + default: + return new AttributeParameter(); + } + } + + public virtual AttributeParameterKind Kind => AttributeParameterKind.Unknown; + } + + public class AttributeParameterLabel : AttributeParameter + { + public AttributeParameterLabel(string label) + { + + ArgumentNullException.ThrowIfNull(label, nameof(label)); + Label = label; + } + + public AttributeParameterLabel(AttributeParameterLabel other) + : this(other.Label) + { + } + + public override AttributeParameterKind Kind => AttributeParameterKind.Label; + public string Label { get; private set; } + } + + public class AttributeParameterLiteral : AttributeParameter + { + public AttributeParameterLiteral(string literal) + { + ArgumentNullException.ThrowIfNull(literal, nameof(literal)); + Literal = literal; + } + + public AttributeParameterLiteral(AttributeParameterLiteral other) + : this(other.Literal) + { + } + + public override AttributeParameterKind Kind => AttributeParameterKind.Literal; + public string Literal { get; private set; } + } + + public class AttributeParameterSublist : AttributeParameter + { + public AttributeParameterSublist() + { + Parameters = new List(); + } + + public AttributeParameterSublist(AttributeParameterSublist other) + : this() + { + Parameters.AddRange(other.Parameters.Select(prm => AttributeDeclaration.DuplicateOf(prm))); + } + + public static AttributeParameterSublist SublistFromXElement(XElement elem) + { + var sublist = new AttributeParameterSublist(); + var parameters = elem.Element("attributeparameterlist"); + if (parameters == null) + return sublist; + AttributeDeclaration.FromAttributeParameterList(parameters, sublist.Parameters); + return sublist; + } + + public override AttributeParameterKind Kind => AttributeParameterKind.Sublist; + public List Parameters { get; private set; } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/BaseConstraint.cs b/src/SwiftReflector/src/SwiftXmlReflection/BaseConstraint.cs new file mode 100644 index 000000000000..529eb3a7334f --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/BaseConstraint.cs @@ -0,0 +1,242 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Xml.Linq; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class BaseConstraint : IXElementConvertible + { + protected BaseConstraint(ConstraintKind kind) + { + Kind = kind; + } + public ConstraintKind Kind { get; private set; } + + public static BaseConstraint FromXElement(TypeAliasFolder folder, XElement elem) + { + if (elem == null) + return null; + if ((string)elem.Attribute("relationship") == "inherits") + { + return new InheritanceConstraint((string)elem.Attribute("name"), (string)elem.Attribute("from"), folder); + } + else + { + return new EqualityConstraint((string)elem.Attribute("firsttype"), (string)elem.Attribute("secondtype"), folder); + } + } + + public XElement ToXElement() + { + var inh = this as InheritanceConstraint; + if (inh != null) + { + return new XElement("where", new XAttribute("relationship", "inherits"), + new XAttribute("name", inh.Name), + new XAttribute("from", inh.Inherits)); + } + else + { + var eq = (EqualityConstraint)this; + return new XElement("where", new XAttribute("relationship", "equals"), + new XAttribute("firsttype", eq.Type1), + new XAttribute("secondtype", eq.Type2)); + } + } + + internal string EffectiveTypeName() + { + var inh = this as InheritanceConstraint; + if (inh != null) + return inh.Name; + var eq = (EqualityConstraint)this; + string[] pieces = eq.Type1.Split('.'); + // T, T.U + if (pieces.Length == 1 || pieces.Length == 2) + { + return pieces[0]; + } + // Module.T.U + else if (pieces.Length > 2) + { + return pieces[1]; + } + return null; + } + + public static BaseConstraint CopyOf(BaseConstraint baseConstraint) + { + if (baseConstraint is InheritanceConstraint inh) + { + return new InheritanceConstraint(inh.Name, inh.Inherits); + + } + else if (baseConstraint is EqualityConstraint eq) + { + return new EqualityConstraint(eq.Type1, eq.Type2); + } + throw new NotImplementedException($"Unknown constraint type {baseConstraint.GetType().Name}"); + } + } + + public class InheritanceConstraint : BaseConstraint + { + public InheritanceConstraint(string name, string inheritsTypeSpecString, TypeAliasFolder folder = null) + : base(ConstraintKind.Inherits) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Name = name; + Inherits = inheritsTypeSpecString; + if (folder != null) + InheritsTypeSpec = folder.FoldAlias(null, InheritsTypeSpec); + } + + public InheritanceConstraint(string name, TypeSpec inheritsTypeSpecString) + : this(name, inheritsTypeSpecString.ToString()) + { + + } + + public string Name { get; private set; } + string inheritsStr; + TypeSpec inheritsSpec; + public string Inherits + { + get + { + return inheritsStr; + } + set + { + inheritsStr = value; + if (value != null) + { + inheritsSpec = TypeSpecParser.Parse(value); + } + else + { + inheritsSpec = null; + } + } + } + public TypeSpec InheritsTypeSpec + { + get + { + return inheritsSpec; + } + set + { + inheritsSpec = value; + if (value != null) + { + inheritsStr = value.ToString(); + } + else + { + inheritsStr = null; + } + } + } + } + + public class EqualityConstraint : BaseConstraint + { + public EqualityConstraint(string type1, string type2, TypeAliasFolder folder = null) + : base(ConstraintKind.Equal) + { + Type1 = type1; + Type2 = type2; + if (folder != null) + { + Type1Spec = folder.FoldAlias(null, Type1Spec); + Type2Spec = folder.FoldAlias(null, Type2Spec); + } + } + string type1Str; + TypeSpec type1Spec; + public string Type1 + { + get + { + return type1Str; + } + set + { + type1Str = value; + if (value != null) + { + type1Spec = TypeSpecParser.Parse(value); + } + else + { + type1Spec = null; + } + } + } + public TypeSpec Type1Spec + { + get + { + return type1Spec; + } + set + { + type1Spec = value; + if (value != null) + { + type1Str = value.ToString(); + } + else + { + type1Str = null; + } + } + } + string type2Str; + TypeSpec type2Spec; + public string Type2 + { + get + { + return type2Str; + } + set + { + type2Str = value; + if (value != null) + { + type2Spec = TypeSpecParser.Parse(value); + } + else + { + type2Spec = null; + } + } + } + public TypeSpec Type2Spec + { + get + { + return type2Spec; + } + set + { + type2Spec = value; + if (value != null) + { + type2Str = value.ToString(); + } + else + { + type2Str = null; + } + } + } + + + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/BaseDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/BaseDeclaration.cs new file mode 100644 index 000000000000..e7b68c39063e --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/BaseDeclaration.cs @@ -0,0 +1,626 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using System.Text; +using SwiftReflector.ExceptionTools; +using SwiftReflector.TypeMapping; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class BaseDeclaration + { + protected BaseDeclaration() + { + Generics = new GenericDeclarationCollection(); + Attributes = new List(); + } + + protected BaseDeclaration(BaseDeclaration other) + { + Name = other.Name; + Access = other.Access; + Module = other.Module; + Parent = other.Parent; + ParentExtension = other.ParentExtension; + Generics = new GenericDeclarationCollection(); + Attributes = new List(); + } + + public string Name { get; set; } + public Accessibility Access { get; set; } + public ModuleDeclaration Module { get; set; } + public BaseDeclaration Parent { get; set; } + public GenericDeclarationCollection Generics { get; private set; } + public ExtensionDeclaration ParentExtension { get; set; } + public bool IsExtension { get { return ParentExtension != null; } } + public bool ContainsGenericParameters + { + get + { + return Generics.Count() > 0; + } + } + public List Attributes { get; private set; } + + public bool IsTypeSpecBoundGeneric(TypeSpec sp) + { + if (sp.ContainsGenericParameters) + { + foreach (var gen in sp.GenericParameters) + { + if (IsTypeSpecGeneric(gen)) + return false; + } + return true; + } + return false; + } + + public bool IsTypeSpecAssociatedType(NamedTypeSpec named) + { + var proto = ThisOrParentProtocol(this); + if (proto == null) + return false; + if (named.ContainsGenericParameters) + { + foreach (var gen in named.GenericParameters) + { + if (gen is NamedTypeSpec namedGen && IsTypeSpecAssociatedType(namedGen)) + return true; + } + } + return proto.AssociatedTypeNamed(named.NameWithoutModule) != null; + } + + public bool IsNested => this is TypeDeclaration && Parent != null; + + public ProtocolDeclaration GetConstrainedProtocolWithAssociatedType(NamedTypeSpec named, TypeMapper typeMapper) + { + var depthIndex = GetGenericDepthAndIndex(named); + if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) + return null; + var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); + if (genDecl == null) + return null; + if (genDecl.Constraints.Count != 1) + return null; + var inheritance = genDecl.Constraints[0] as InheritanceConstraint; + if (inheritance == null) + return null; + var entity = typeMapper.GetEntityForTypeSpec(inheritance.InheritsTypeSpec); + if (entity == null) + return null; + var proto = entity.Type as ProtocolDeclaration; + if (proto == null || !proto.HasAssociatedTypes) + return null; + return proto; + } + + public AssociatedTypeDeclaration AssociatedTypeDeclarationFromNamedTypeSpec(NamedTypeSpec named) + { + var proto = ThisOrParentProtocol(this); + return proto.AssociatedTypeNamed(named.NameWithoutModule); + } + + public ProtocolDeclaration AsProtocolOrParentAsProtocol() + { + return ThisOrParentProtocol(this); + } + + public BaseDeclaration AsTypeDeclaration() + { + return ThisOrParentTypeDeclaration(this); + } + + static ProtocolDeclaration ThisOrParentProtocol(BaseDeclaration self) + { + if (self == null) + return null; + + do + { + if (self is ProtocolDeclaration decl) + return decl; + self = self.Parent; + } while (self != null); + return null; + } + + static TypeDeclaration ThisOrParentTypeDeclaration(BaseDeclaration self) + { + if (self == null) + return null; + + do + { + if (self is TypeDeclaration decl) + return decl; + self = self.Parent; + } while (self != null); + return null; + } + + + public bool IsProtocolWithAssociatedTypesFullPath(NamedTypeSpec named, TypeMapper typeMap) + { + if (named == null) + return false; + return OwningProtocolFromGenericWithFullPath(named, typeMap) != null; + } + + public ProtocolDeclaration OwningProtocolFromGenericWithFullPath(NamedTypeSpec named, TypeMapper typeMap) + { + AssociatedTypeDeclaration assoc = null; + return OwningProtocolAndAssociateTypeFromGenericWithFullPath(named, typeMap, out assoc); + } + + public AssociatedTypeDeclaration AssociatedTypeDeclarationFromGenericWithFullPath(NamedTypeSpec named, TypeMapper typeMap) + { + AssociatedTypeDeclaration assoc = null; + OwningProtocolAndAssociateTypeFromGenericWithFullPath(named, typeMap, out assoc); + return assoc; + } + + ProtocolDeclaration OwningProtocolAndAssociateTypeFromGenericWithFullPath(NamedTypeSpec named, TypeMapper typeMap, out AssociatedTypeDeclaration assoc) + { + assoc = null; + if (named.Name.Contains(".")) + { + var parts = named.Name.Split('.'); + if (IsTypeSpecGeneric(parts[0])) + { + // I make assertions about why things can't happen. Here's why: + // If we have func foo(a:T b:T.Foo) + // it means that if the T part of T.Foo is a generic, then T HAS to be + // constrained to a protocol with associated types + // If T.Foo is a path to an associated type, then it + var depthIndex = GetGenericDepthAndIndex(parts[0]); + if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) + return null; + var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); + if (genDecl.Constraints.Count != 1) // pretty sure this can't ever happen + return null; + var inh = genDecl.Constraints[0] as InheritanceConstraint; + if (inh == null) // pretty sure this also can't ever happen + return null; + var entity = typeMap.GetEntityForTypeSpec(inh.InheritsTypeSpec); + if (entity == null) // Also can't happen + return null; + if (entity.EntityType != EntityType.Protocol) + return null; // Also can't happen + var protocol = entity.Type as ProtocolDeclaration; + if (protocol != null && protocol.HasAssociatedTypes && (assoc = protocol.AssociatedTypeNamed(parts[1])) != null) + { + return protocol; + } + } + } + return null; + } + + public ProtocolDeclaration OwningProtocolFromConstrainedGeneric(NamedTypeSpec named, TypeMapper typeMap) + { + var depthIndex = GetGenericDepthAndIndex(named); + if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) + return null; + var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); + return OwningProtocolFromConstrainedGeneric(genDecl, typeMap); + } + + public ProtocolDeclaration OwningProtocolFromConstrainedGeneric(GenericDeclaration generic, TypeMapper typeMap) + { + var refProto = RefProtoFromConstrainedGeneric(generic, typeMap); + return refProto?.Protocol; + } + + public AssociatedTypeDeclaration AssociatedTypeDeclarationFromConstrainedGeneric(NamedTypeSpec named, TypeMapper typeMap) + { + var depthIndex = GetGenericDepthAndIndex(named); + if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) + return null; + var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); + return AssociatedTypeDeclarationFromConstrainedGeneric(genDecl, typeMap); + } + + public AssociatedTypeDeclaration AssociatedTypeDeclarationFromConstrainedGeneric(GenericDeclaration generic, TypeMapper typeMap) + { + // looking for where U == T.At1[.At2...] + if (generic.Constraints.Count != 1) + return null; + var eqConstraint = generic.Constraints[0] as EqualityConstraint; + if (eqConstraint == null) + return null; + var namedSpec = eqConstraint.Type2Spec as NamedTypeSpec; + if (namedSpec == null) + return null; + var parts = namedSpec.Name.Split('.'); + if (parts.Length <= 1) + return null; + if (!IsTypeSpecGeneric(parts[0])) + return null; + var refProto = GetConstrainedAssociatedTypeProtocol(new NamedTypeSpec(parts[0]), typeMap); + if (refProto == null) + return null; + if (parts.Length > 2) + throw new NotImplementedException($"Not currently supporting equality constraints of nested associated types (yet) {eqConstraint.Type1} == {eqConstraint.Type2}"); + return refProto.Protocol.AssociatedTypeNamed(parts[1]); + } + + public GenericReferenceAssociatedTypeProtocol RefProtoFromConstrainedGeneric(GenericDeclaration generic, TypeMapper typeMap) + { + // looking for where U == T.At1[.At2...] + if (generic.Constraints.Count != 1) + return null; + var eqConstraint = generic.Constraints[0] as EqualityConstraint; + if (eqConstraint == null) + return null; + var namedSpec = eqConstraint.Type2Spec as NamedTypeSpec; + if (namedSpec == null) + return null; + var parts = namedSpec.Name.Split('.'); + if (parts.Length <= 1) + return null; + if (!IsTypeSpecGeneric(parts[0])) + return null; + return GetConstrainedAssociatedTypeProtocol(new NamedTypeSpec(parts[0]), typeMap); + } + + public bool IsEqualityConstrainedByAssociatedType(NamedTypeSpec name, TypeMapper typeMap) + { + var depthIndex = GetGenericDepthAndIndex(name); + if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) + return false; + var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); + return IsEqualityConstrainedByAssociatedType(genDecl, typeMap); + } + + public bool IsEqualityConstrainedByAssociatedType(GenericDeclaration generic, TypeMapper typeMap) + { + return AssociatedTypeDeclarationFromConstrainedGeneric(generic, typeMap) != null; + } + + public GenericReferenceAssociatedTypeProtocol GetConstrainedAssociatedTypeProtocol(NamedTypeSpec spec, TypeMapper typeMap) + { + // we're looking for the pattern T, where T is a generic or contains a generic (Foo) + // and there exists a where T : SomeProtocol + if (spec == null) + return null; + GenericReferenceAssociatedTypeProtocol result = null; + if (spec.ContainsGenericParameters) + { + foreach (var gen in spec.GenericParameters) + { + // recurse on generic element + result = GetConstrainedAssociatedTypeProtocol(gen as NamedTypeSpec, typeMap); + if (result != null) + break; + } + } + else + { + // which declaration has this generic + var owningContext = FindOwningContext(this, spec); + if (owningContext != null) + { + foreach (var genPart in Generics) + { + if (genPart.Name != spec.Name) + continue; + // genPart is the one we care about - now look for a constraint. + foreach (var constraint in genPart.Constraints) + { + // Is it inheritance? + if (constraint is InheritanceConstraint inheritance) + { + // Find the entity in the database + var entity = typeMap.TypeDatabase.EntityForSwiftName(inheritance.Inherits); + // Is it a protocol and it has associated types + if (entity != null && entity.Type is ProtocolDeclaration proto && (proto.HasAssociatedTypes || proto.HasDynamicSelfInArguments)) + result = new GenericReferenceAssociatedTypeProtocol() + { + GenericPart = spec, + Protocol = proto + }; + } + } + if (result != null) + break; + } + } + } + return result; + } + + static BaseDeclaration FindOwningContext(BaseDeclaration context, NamedTypeSpec spec) + { + while (context != null) + { + foreach (var genPart in context.Generics) + { + if (genPart.Name == spec.Name) + return context; + } + context = context.Parent; + } + return null; + } + + public bool IsTypeSpecGeneric(TypeSpec sp) + { + if (sp.ContainsGenericParameters) + { + foreach (var gen in sp.GenericParameters) + { + if (IsTypeSpecGeneric(gen)) + return true; + } + } + + if (sp is NamedTypeSpec named) + { + return IsTypeSpecGeneric(named.Name); + } + else if (sp is ClosureTypeSpec closure) + { + return IsTypeSpecGeneric(closure.Arguments) || IsTypeSpecGeneric(closure.ReturnType); + } + else if (sp is TupleTypeSpec tuple) + { + foreach (var tupSpec in tuple.Elements) + { + if (IsTypeSpecGeneric(tupSpec)) + return true; + } + return false; + } + else if (sp is ProtocolListTypeSpec) + { + // protocol list type specs can't be generic. + return false; + } + else + { + throw new NotImplementedException($"Unknown TypeSpec type {sp.GetType().Name}"); + } + } + + public bool IsTypeSpecGenericReference(TypeSpec sp) + { + if (sp.ContainsGenericParameters) + return false; + var ns = sp as NamedTypeSpec; + return ns != null && IsTypeSpecGeneric(ns.Name); + } + + public bool IsTypeSpecGenericMetatypeReference(TypeSpec sp) + { + if (sp.ContainsGenericParameters) + return false; + string notUsed; + return sp is NamedTypeSpec ns && IsTypeSpecGenericMetatypeReference(ns.Name, out notUsed); + } + + public bool IsTypeSpecGenericMetatypeReference(string typeSpecName, out string genericPart) + { + if (typeSpecName.Contains('.')) + { + var parts = typeSpecName.Split('.'); + if (parts.Length == 2 && parts[1] == "Type") + { + genericPart = parts[0]; + return true; + } + } + genericPart = null; + return false; + } + + public bool IsTypeSpecGeneric(string typeSpecName) + { + string genericPart; + if (IsTypeSpecGenericMetatypeReference(typeSpecName, out genericPart)) + { + return IsTypeSpecGeneric(genericPart); + } + else + { + foreach (GenericDeclaration gendecl in Generics) + { + if (typeSpecName == gendecl.Name) + return true; + } + if (Parent != null) + { + return Parent.IsTypeSpecGeneric(typeSpecName); + } + else + { + return false; + } + } + } + + public int GetTotalDepth() + { + int depth = 0; + BaseDeclaration bd = this; + while (bd.Parent != null) + { + if (Parent.ContainsGenericParameters) + depth++; + bd = bd.Parent; + } + return depth; + } + + public Tuple GetGenericDepthAndIndex(string name) + { + return GetGenericDepthAndIndex(name, GetTotalDepth()); + } + + public Tuple GetGenericDepthAndIndex(TypeSpec spec) + { + var ns = spec as NamedTypeSpec; + if (ns == null) + throw ErrorHelper.CreateError(ReflectorError.kCompilerBase + 5, $"Can't get generic depth from a {spec.GetType().Name}."); + return GetGenericDepthAndIndex(ns.Name); + } + + Tuple GetGenericDepthAndIndex(string name, int depth) + { + string genericPart; + if (IsTypeSpecGenericMetatypeReference(name, out genericPart)) + { + return GetGenericDepthAndIndex(genericPart, depth); + } + else + { + for (int i = 0; i < Generics.Count; i++) + { + if (Generics[i].Name == name) + return new Tuple(depth, i); + } + if (Parent != null) + { + return Parent.GetGenericDepthAndIndex(name, depth - 1); + } + return new Tuple(-1, -1); + } + } + + public GenericDeclaration GetGeneric(int depth, int index) + { + var parentsToWalk = GetMaxDepth() - depth; + BaseDeclaration decl = this; + do + { + // skip runs of no generics + while (!decl.ContainsGenericParameters) + { + decl = decl.Parent; + } + if (parentsToWalk > 0) + { + parentsToWalk--; + decl = decl.Parent; + } + } while (parentsToWalk > 0); + return decl.Generics[index]; + } + + + int GetMaxDepth(int depth) + { + depth += (ContainsGenericParameters ? 1 : 0); + if (Parent == null) + return depth; + return Parent.GetMaxDepth(depth); + } + + public int GetMaxDepth() + { + return GetMaxDepth(-1); + } + + public bool IsPublicOrOpen + { + get + { + return Access == Accessibility.Public || Access == Accessibility.Open; + } + } + + + public static BaseDeclaration FromXElement(TypeAliasFolder folder, XElement elem, ModuleDeclaration module, BaseDeclaration parent) + { + var generics = GenericDeclaration.FromXElement(folder, elem.Element("genericparameters")); + BaseDeclaration decl = null; + switch (elem.Name.ToString()) + { + case "func": + decl = FunctionDeclaration.FuncFromXElement(folder, elem, module, parent); + break; + case "typedeclaration": + decl = TypeDeclaration.TypeFromXElement(folder, elem, module, parent); + break; + case "property": + decl = PropertyDeclaration.PropFromXElement(folder, elem, module, parent); + break; + default: + decl = new BaseDeclaration + { + Name = (string)elem.Attribute("name"), + Access = TypeDeclaration.AccessibilityFromString((string)elem.Attribute("accessibility")) + }; + break; + } + decl.Generics.AddRange(generics); + decl.Attributes.AddRange(AttributesFromXElement(elem.Element("attributes"))); + return decl; + } + + internal static IEnumerable AttributesFromXElement(XElement elem) + { + if (elem == null) + return Enumerable.Empty(); + return elem.Elements("attribute").Select(attr => AttributeDeclaration.FromXElement(attr)); + } + + public virtual string ToFullyQualifiedName(bool includeModule = true) + { + var sb = new StringBuilder(); + BaseDeclaration decl = this; + // recursion? We don't need to stinking recursion! + while (decl != null) + { + TypeDeclaration typeDecl = decl as TypeDeclaration; + // unrooted types have no parent, but do have a fully qualified name + if (typeDecl != null && typeDecl.IsUnrooted) + { + sb.Insert(0, typeDecl.ToFullyQualifiedName(false)); + break; + } + else + { + sb.Insert(0, decl.Name); + decl = decl.Parent; + if (decl != null) + sb.Insert(0, '.'); + } + } + if (includeModule) + { + sb.Insert(0, '.').Insert(0, Module.Name); + } + return sb.ToString(); + } + + public virtual string ToFullyQualifiedNameWithGenerics() + { + var sb = new StringBuilder(ToFullyQualifiedName()); + if (ContainsGenericParameters) + { + sb.Append("<"); + for (int i = 0; i < Generics.Count; i++) + { + if (i > 0) + sb.Append(", "); + sb.Append(Generics[i].Name); + } + sb.Append(">"); + } + return sb.ToString(); + } + + public override string ToString() + { + return ToFullyQualifiedNameWithGenerics(); + } + } + +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/ClassDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/ClassDeclaration.cs new file mode 100644 index 000000000000..95153a4c0ff3 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/ClassDeclaration.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; +using SyntaxDynamo.CSLang; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class ClassDeclaration : TypeDeclaration + { + public ClassDeclaration() + : base() + { + Kind = TypeKind.Class; + CSharpMethods = new List(); + CSharpProperties = new List(); + } + + protected override TypeDeclaration UnrootedFactory() + { + return new ClassDeclaration(); + } + + // These are strictly for imported members from C# dll's. + // These members should not get serialized. + public bool IsImportedBinding { get; set; } + public List CSharpMethods { get; } + public List CSharpProperties { get; } + } + +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/EnumDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/EnumDeclaration.cs new file mode 100644 index 000000000000..ebbfafd1b0b7 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/EnumDeclaration.cs @@ -0,0 +1,149 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SwiftReflector.ExceptionTools; +using System.Xml.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class EnumDeclaration : TypeDeclaration + { + public EnumDeclaration() + : base() + { + Kind = TypeKind.Enum; + Elements = new List(); + } + + protected override TypeDeclaration UnrootedFactory() + { + return new EnumDeclaration(); + } + + protected override void CompleteUnrooting(TypeDeclaration unrooted) + { + base.CompleteUnrooting(unrooted); + EnumDeclaration enumDecl = unrooted as EnumDeclaration; + if (enumDecl == null) + throw new ArgumentException("unrooted type was not constructed by EnumDeclaration"); + enumDecl.Elements.AddRange(Elements); + } + + public List Elements { get; private set; } + public bool ElementIsGeneric(EnumElement element) + { + return IsTypeSpecGeneric(element.TypeSpec); + } + + public bool HasRawType { get { return rawTypeName != null && RawTypeSpec != null; } } + + string rawTypeName; + public string RawTypeName + { + get + { + return rawTypeName; + } + set + { + rawTypeName = value; + if (value == null) + RawTypeSpec = null; + else + { + try + { + RawTypeSpec = TypeSpecParser.Parse(rawTypeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 8, $"Unable to parse type name '{rawTypeName}': {ex.Message}"); + } + } + } + } + public TypeSpec RawTypeSpec { get; private set; } + + public bool IsTrivial + { + get + { + if (HasRawType) + return false; + if (Inheritance.Count > 0) + return false; + foreach (EnumElement elem in Elements) + { + if (elem.HasType) + return false; + } + return true; + } + } + + public bool IsIntegral + { + get + { + if (HasRawType) + { + return TypeSpec.IsIntegral(RawTypeSpec); + } + foreach (EnumElement elem in Elements) + { + if (elem.HasType && !TypeSpec.IsIntegral(elem.TypeSpec)) + return false; + } + return true; + } + } + + public bool IsHomogenous + { + get + { + if (Elements.Count == 0) + return true; + TypeSpec firstSpec = Elements[0].TypeSpec; + for (int i = 1; i < Elements.Count; i++) + { + TypeSpec nextSpec = Elements[i].TypeSpec; + if (firstSpec == null) + { + if (firstSpec != nextSpec) + return false; + } + else + { + if (!firstSpec.Equals(nextSpec)) + return false; + } + } + return true; + } + } + + public EnumElement this[string s] + { + get + { + return Elements.FirstOrDefault(elem => elem.Name == s); + } + } + + + protected override void GatherXObjects(List xobjects) + { + base.GatherXObjects(xobjects); + if (HasRawType) + xobjects.Add(new XAttribute("rawType", RawTypeName)); + IEnumerable elems = Elements.Select(e => e.ToXElement()); + xobjects.Add(new XElement("elements", elems.ToArray())); + } + + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/EnumElement.cs b/src/SwiftReflector/src/SwiftXmlReflection/EnumElement.cs new file mode 100644 index 000000000000..b37c06759366 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/EnumElement.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SwiftReflector.ExceptionTools; +using System.Xml.Linq; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class EnumElement : IXElementConvertible + { + public EnumElement(string name, string typeName, long? value) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Name = name; + TypeName = typeName; + Value = value; + } + + public string Name { get; set; } + public bool HasType { get { return typeName != null && TypeSpec != null; } } + string typeName; + public string TypeName + { + get + { + return typeName; + } + set + { + typeName = value; + if (value == null) + TypeSpec = null; + else + { + try + { + TypeSpec = TypeSpecParser.Parse(typeName); + } + catch (RuntimeException ex) + { + ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 9, $"Unable to parse type name '{typeName}': {ex.Message}"); + } + } + } + } + public TypeSpec TypeSpec { get; private set; } + public long? Value { get; private set; } + + #region IXElementConvertible implementation + public XElement ToXElement() + { + XElement elem = new XElement("element", + new XAttribute("name", Name)); + if (HasType) + elem.Add(new XAttribute("type", TypeName)); + if (Value.HasValue) + elem.Add("intValue", Value.Value); + return elem; + } + #endregion + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/Enums.cs b/src/SwiftReflector/src/SwiftXmlReflection/Enums.cs new file mode 100644 index 000000000000..c9cfd7b884fe --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/Enums.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SwiftReflector.SwiftXmlReflection +{ + public enum TypeKind + { + Unknown = 0, + Class, + Struct, + Enum, + Protocol + } + + public enum Accessibility + { + Unknown = 0, + Public, + Private, + Internal, + Open, + } + + public enum StorageKind + { + Unknown = 0, + Addressed, + AddressedWithObservers, + AddressedWithTrivialAccessors, + Computed, + ComputedWithMutableAddress, + Inherited, + InheritedWithObservers, + Stored, + StoredWithObservers, + StoredWithTrivialAccessors, + Coroutine, + MutableAddressor, + } + + public enum TypeSpecKind + { + Named = 0, + Tuple, + Closure, + ProtocolList, + } + + public enum TypeTokenKind + { + TypeName, + Comma, + LeftParenthesis, + RightParenthesis, + LeftAngle, + RightAngle, + LeftBracket, + RightBracket, + Arrow, + At, + QuestionMark, + TypeLabel, + Colon, + ExclamationPoint, + Period, + Ampersand, + Done, + } + + public enum InheritanceKind + { + Class, + Protocol + } + + public enum ConstraintKind + { + Inherits, + Equal + } + + public enum AttributeParameterKind + { + None, + Label, + Literal, + Sublist, + Unknown, + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/ExtensionDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/ExtensionDeclaration.cs new file mode 100644 index 000000000000..0e4f8223c56a --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/ExtensionDeclaration.cs @@ -0,0 +1,100 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using SwiftReflector.ExceptionTools; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class ExtensionDeclaration : IXElementConvertible + { + + public ExtensionDeclaration() + { + Inheritance = new List(); + Members = new List(); + } + + public ExtensionDeclaration(ExtensionDeclaration other) + : this() + { + Inheritance.AddRange(other.Inheritance); + Members.AddRange(other.Members); + ExtensionOnTypeName = other.ExtensionOnTypeName; + Module = other.Module; + } + + public ModuleDeclaration Module { get; set; } + public List Inheritance { get; set; } + string extensionOnTypeName; + public string ExtensionOnTypeName + { + get + { + return extensionOnTypeName; + } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + extensionOnTypeName = value; + try + { + ExtensionOnType = TypeSpecParser.Parse(extensionOnTypeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase, $"Unable to parse type name '{extensionOnTypeName}': {ex.Message}"); + } + + } + } + public TypeSpec ExtensionOnType { get; private set; } + public List Members { get; set; } + + public XElement ToXElement() + { + var xobjects = new List(); + GatherXObjects(xobjects); + XElement typeDecl = new XElement("extension", xobjects.ToArray()); + return typeDecl; + } + + void GatherXObjects(List xobjects) + { + xobjects.Add(new XAttribute("onType", ExtensionOnTypeName)); + List memcontents = new List(Members.Select(m => m.ToXElement())); + xobjects.Add(new XElement("members", memcontents.ToArray())); + List inherits = new List(Inheritance.Select(i => i.ToXElement())); + xobjects.Add(new XElement("inherits", inherits.ToArray())); + } + + public static ExtensionDeclaration FromXElement(TypeAliasFolder folder, XElement elem, ModuleDeclaration module) + { + var decl = new ExtensionDeclaration(); + decl.Module = module; + decl.ExtensionOnTypeName = (string)elem.Attribute("onType"); + decl.ExtensionOnType = folder.FoldAlias(null, decl.ExtensionOnType); + if (elem.Element("members") != null) + { + var members = from mem in elem.Element("members").Elements() + select Member.FromXElement(folder, mem, module, null) as Member; + decl.Members.AddRange(members); + foreach (var member in decl.Members) + { + member.ParentExtension = decl; + } + } + if (elem.Element("inherits") != null) + { + var inherits = from inherit in elem.Element("inherits").Elements() + select SwiftReflector.SwiftXmlReflection.Inheritance.FromXElement(folder, inherit) as Inheritance; + decl.Inheritance.AddRange(inherits); + } + return decl; + } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/ExtensionMethods.cs b/src/SwiftReflector/src/SwiftXmlReflection/ExtensionMethods.cs new file mode 100644 index 000000000000..7d976c86cf88 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/ExtensionMethods.cs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Xml.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + + public static class ExtensionMethods + { + // surprise! You'd think that you could write this code: + // public static T DefaultedAttribute(this XElement elem, XName name, T defaultValue = default(T)) + // { + // XAttribute attr = elem.Attribute (name); + // if (attr == null) + // return defaultValue; + // return (T)attr; + // } + // but the last cast won't work because generics aren't templates. + + // So instead, we get to repeat ourselves a lot. + + public static bool BoolAttribute(this XElement elem, XName name, bool defaultValue = default(bool)) + { + XAttribute attr = elem.Attribute(name); + if (attr == null) + return defaultValue; + return (bool)attr; + } + + public static double DoubleAttribute(this XElement elem, XName name, double defaultValue = default(double)) + { + XAttribute attr = elem.Attribute(name); + if (attr == null) + return defaultValue; + return (double)attr; + } + + public static bool IsPrivateOrInternal(this Accessibility a) + { + return a == Accessibility.Private || a == Accessibility.Internal; + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/FunctionDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/FunctionDeclaration.cs new file mode 100644 index 000000000000..f114f59a4fb9 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/FunctionDeclaration.cs @@ -0,0 +1,542 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using SwiftReflector.ExceptionTools; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class FunctionDeclaration : Member + { + public const string kConstructorName = ".ctor"; + public const string kDestructorName = ".dtor"; + public const string kPropertyGetterPrefix = "get_"; + public const string kPropertySetterPrefix = "set_"; + public const string kPropertyMaterializerPrefix = "materializeforset_"; + public const string kPropertySubscriptGetterName = "get_subscript"; + public const string kPropertySubscriptSetterName = "set_subscript"; + public const string kPropertySubscriptMaterializerName = "materializeforset_subscript"; + + static string[] subscriptNames = new string[] { + kPropertySubscriptGetterName, + kPropertySubscriptSetterName, + kPropertySubscriptMaterializerName, + }; + static bool IsSubscriptName(string s) + { + return Array.IndexOf(subscriptNames, s) >= 0; + } + + public FunctionDeclaration() + : base() + { + ParameterLists = new List>(); + } + + public FunctionDeclaration(FunctionDeclaration other) + : base(other) + { + ParameterLists = CopyOf(other.ParameterLists); + ReturnTypeName = other.ReturnTypeName; + IsProperty = other.IsProperty; + IsStatic = other.IsStatic; + IsFinal = other.IsFinal; + HasThrows = other.HasThrows; + IsDeprecated = other.IsDeprecated; + IsUnavailable = other.IsUnavailable; + OperatorType = other.OperatorType; + IsOptional = other.IsOptional; + ObjCSelector = other.ObjCSelector; + IsRequired = other.IsRequired; + IsConvenienceInit = other.IsConvenienceInit; + IsAsync = other.IsAsync; + foreach (var genDecl in other.Generics) + { + Generics.Add(new GenericDeclaration(genDecl)); + } + } + + string returnTypeName; + public string ReturnTypeName + { + get { return returnTypeName; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + returnTypeName = value; + try + { + ReturnTypeSpec = TypeSpecParser.Parse(returnTypeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 1, $"Unable to parse type name '{returnTypeName}': {ex.Message}"); + } + } + } + + + // When writing an override, we need to keep around the function in the override + // this member should never get serialized. Ever. + public FunctionDeclaration OverrideSurrogateFunction { get; set; } + + + public TypeSpec ReturnTypeSpec { get; set; } + + public bool IsRequired { get; set; } + public string ObjCSelector { get; set; } + public bool IsOptional { get; set; } + public bool HasThrows { get; set; } + public bool IsAsync { get; set; } + public bool IsProperty { get; set; } + public string PropertyName { get { return Name.Substring(kPropertyGetterPrefix.Length); } } + public bool IsStatic { get; set; } + public bool IsFinal { get; set; } + public bool IsOperator { get { return OperatorType != OperatorType.None; } } + public bool IsDeprecated { get; set; } + public bool IsUnavailable { get; set; } + public bool IsConvenienceInit { get; set; } + public bool IsVirtualClassMethod { get { return IsStatic && Access == Accessibility.Open; } } + public string MangledName { get; set; } + public bool IsSubscript + { + get + { + return IsProperty && IsSubscriptName(Name); + } + } + public OperatorType OperatorType { get; set; } + public bool IsSubscriptGetter + { + get + { + return IsProperty && Name == kPropertySubscriptGetterName; + } + } + public bool IsSubscriptSetter + { + get + { + return IsProperty && Name == kPropertySubscriptSetterName; + } + } + // in practice, this is useless since it is near impossible to disambiguate it + // and it has no actual use from our point of view. Materializers are code used + // internally by the compiler and we don't really have access to this. + public bool IsSubscriptMaterializer + { + get + { + return IsProperty && Name == kPropertySubscriptMaterializerName; + } + } + + public TypeSpec PropertyType + { + get + { + if (!IsProperty) + throw ErrorHelper.CreateError(ReflectorError.kInventoryBase + 17, $"Attempt to get property type for a function named {this.Name}"); + // newValue should be the first argument in the last argument list. + return ParameterLists.Last()[0].TypeSpec; + } + } + + public List> ParameterLists { get; set; } + + public bool IsTypeSpecGeneric(ParameterItem item) + { + return IsTypeSpecGeneric(item.TypeSpec); + } + + public int GenericParameterCount + { + get + { + return ParameterLists.Last().Sum(pi => IsTypeSpecGeneric(pi) ? 1 : 0); + } + } + + public bool MatchesSignature(FunctionDeclaration other, bool ignoreFirstParameterListIfPresent) + { + if (!TypeSpec.BothNullOrEqual(this.ReturnTypeSpec, other.ReturnTypeSpec)) + return false; + if (this.ParameterLists.Count != other.ParameterLists.Count) + return false; + int startIndex = ignoreFirstParameterListIfPresent && this.ParameterLists.Count > 1 ? 1 : 0; + + for (int i = startIndex; i < this.ParameterLists.Count; i++) + { + if (!ParameterItem.AreEqualIgnoreNamesReferencesInvariant(this, this.ParameterLists[i], other, other.ParameterLists[i], true)) + return false; + } + return true; + } + + public bool IsConstructor { get { return Name == kConstructorName; } } + public bool IsDestructor { get { return Name == kDestructorName; } } + public bool IsConstructorOrDestructor { get { return IsConstructor || IsDestructor; } } + public bool IsGetter { get { return IsProperty && Name.StartsWith(kPropertyGetterPrefix); } } + public bool IsSetter { get { return IsProperty && Name.StartsWith(kPropertySetterPrefix); } } + public bool IsMaterializer { get { return IsProperty && Name.StartsWith(kPropertyMaterializerPrefix); } } + + public bool IsOptionalConstructor + { + get + { + if (Name != kConstructorName) + return false; + var namedSpec = ReturnTypeSpec as NamedTypeSpec; + if (namedSpec == null) + return false; + if (namedSpec.Name != "Swift.Optional") + return false; + if (namedSpec.GenericParameters.Count != 1) + return false; + // previously we did a name check on the parent but in the case of + // a virtual class, the name could be the proxy class that we make + // and won't necessarily match. + return true; + } + } + + public bool IsVariadic + { + get + { + return ParameterLists.Last().Any(pi => pi.IsVariadic); + } + } + + public FunctionDeclaration MatchingSetter(IEnumerable decls) + { + if (!IsProperty) + return null; + if (IsSubscript) + { + return decls.Where(f => f.IsSubscriptSetter && SubscriptParametersMatch(this, f)).FirstOrDefault(); + } + else + { + return decls.Where(f => f.IsSetter && f.PropertyName == PropertyName).FirstOrDefault(); + } + } + + static bool SubscriptParametersMatch(FunctionDeclaration getter, FunctionDeclaration setter) + { + if (getter.ParameterLists.Count != 2 || setter.ParameterLists.Count != 2) + return false; + TypeSpec returnType = getter.ReturnTypeSpec; + if (getter.ParameterLists[1].Count != setter.ParameterLists[1].Count - 1) + return false; + if (!returnType.Equals(setter.ParameterLists[1][0].TypeSpec)) + return false; + + return ParameterItem.AreEqualIgnoreNamesReferencesInvariant(getter, getter.ParameterLists[1], + setter, setter.ParameterLists[1].Skip(1).ToList(), true); + } + + + public bool ContainsBoundGenericClosure() + { + foreach (var arg in ParameterLists.Last()) + { + if (arg.TypeSpec.ContainsBoundGenericClosure()) + return true; + } + return ReturnTypeSpec.ContainsBoundGenericClosure(); + } + + + public static FunctionDeclaration FuncFromXElement(TypeAliasFolder folder, XElement elem, ModuleDeclaration module, BaseDeclaration parent) + { + ArgumentNullException.ThrowIfNull((string)elem.Attribute("returnType"), "returnType"); + FunctionDeclaration decl = new FunctionDeclaration + { + Name = (string)elem.Attribute("name"), + Module = module, + Parent = parent, + Access = TypeDeclaration.AccessibilityFromString((string)elem.Attribute("accessibility")), + ReturnTypeName = (string)elem.Attribute("returnType"), + IsAsync = elem.BoolAttribute("isAsync"), + IsProperty = elem.BoolAttribute("isProperty"), + IsStatic = elem.BoolAttribute("isStatic"), + IsFinal = elem.BoolAttribute("isFinal"), + OperatorType = OperatorTypeFromElement((string)elem.Attribute("operatorKind")), + HasThrows = elem.BoolAttribute("hasThrows"), + IsDeprecated = elem.BoolAttribute("isDeprecated"), + IsUnavailable = elem.BoolAttribute("isUnavailable"), + IsOptional = elem.BoolAttribute("isOptional"), + ObjCSelector = (string)elem.Attribute("objcSelector"), + IsRequired = elem.BoolAttribute("isRequired"), + IsConvenienceInit = elem.BoolAttribute("isConvenienceInit") + }; + decl.ReturnTypeSpec = folder.FoldAlias(parent, decl.ReturnTypeSpec); + decl.ParameterLists.AddRange(ParameterItem.ParameterListListFromXElement(folder, elem.Element("parameterlists"))); + if (decl.IsProperty && (decl.IsSetter || decl.IsSubscriptSetter)) + { + decl.ParameterLists[decl.ParameterLists.Count - 1] = + MassageLastPropertySetterParameterList(decl.ParameterLists.Last()); + } + return decl; + } + + static List MassageLastPropertySetterParameterList(List list) + { + if (list.Count == 0) + return list; // should never happen, but... + + if (list.Any(pi => pi.PublicName == "newValue")) + return list; // also should never happen, but... + + var firstParam = list[0]; + var firstParamName = firstParam.NameIsRequired ? firstParam.PublicName : firstParam.PrivateName; + // why the check on both value and newValue? Because we want both the public and private names to be newValue + if (firstParamName == "value" || firstParamName == "newValue") // because swift reflects this incorrectly + { + firstParam.PublicName = firstParam.PrivateName = "newValue"; + } + + return list; + } + + + protected override XElement MakeXElement() + { + XElement theFunc = new XElement("func", + new XAttribute("name", Name), + new XAttribute("accessibility", TypeDeclaration.ToString(Access)), + new XAttribute("returnType", ReturnTypeName), + new XAttribute("isAsync", BoolString(IsAsync)), + new XAttribute("isProperty", BoolString(IsProperty)), + new XAttribute("isStatic", BoolString(IsStatic)), + new XAttribute("isFinal", BoolString(IsFinal)), + new XAttribute("isDeprecated", BoolString(IsDeprecated)), + new XAttribute("isUnavailable", BoolString(IsUnavailable)), + new XAttribute("isOptional", BoolString(IsOptional)), + new XAttribute("operatorKind", OperatorType.ToString()), + new XAttribute("hasThrows", BoolString(HasThrows)), + new XAttribute("isRequired", BoolString(IsRequired)), + new XAttribute("isConvenienceInit", BoolString(IsConvenienceInit)), + new XElement("parameterlists", MakeParamListXElement())); + if (!String.IsNullOrEmpty(ObjCSelector)) + theFunc.Add(new XAttribute("objcSelector", ObjCSelector)); + return theFunc; + } + + XElement[] MakeParamListXElement() + { + List plists = new List(); + int index = 0; + foreach (List list in ParameterLists) + { + XElement thisList = new XElement("parameterlist", + new XAttribute("index", index), + list.Select((pi, i) => + { + XElement elem = pi.ToXElement(); + elem.Add(new XAttribute("index", i)); + return elem; + }).ToArray()); + plists.Add(thisList); + index++; + } + return plists.ToArray(); + } + + static List> CopyOf(List> src) + { + List> dst = new List>(); + dst.AddRange(src.Select(l => CopyOf(l))); + return dst; + } + + static List CopyOf(List src) + { + List dst = new List(); + dst.AddRange(src.Select(pi => new ParameterItem(pi))); + return dst; + } + + public static OperatorType OperatorTypeFromElement(string type) + { + var enumType = OperatorType.None; + if (Enum.TryParse(type, out enumType)) + return enumType; + return OperatorType.None; + } + + static string BoolString(bool b) + { + return b ? "true" : "false"; + } + + string PropertyKindString + { + get + { + if (IsSubscriptGetter || IsGetter) + { + return "get"; + } + else if (IsSubscriptSetter || IsSetter) + { + return "set"; + } + else if (IsSubscriptMaterializer || IsMaterializer) + { + return "materialize"; + } + return ""; + } + } + + public override bool HasDynamicSelf + { + get + { + var types = ParameterLists.Last().Select(p => p.TypeSpec).ToList(); + if (!TypeSpec.IsNullOrEmptyTuple(ReturnTypeSpec)) + types.Add(ReturnTypeSpec); + return TypeSpec.AnyHasDynamicSelf(types); + } + } + + public override bool HasDynamicSelfInReturnOnly + { + get + { + if (IsProperty && !IsSubscript) + return false; + if (TypeSpec.IsNullOrEmptyTuple(ReturnTypeSpec) || !ReturnTypeSpec.HasDynamicSelf) + return false; + var types = ParameterLists.Last().Select(p => p.TypeSpec).ToList(); + return !TypeSpec.AnyHasDynamicSelf(types); + } + } + + public override bool HasDynamicSelfInArguments + { + get + { + return TypeSpec.AnyHasDynamicSelf(ParameterLists.Last().Select(p => p.TypeSpec).ToList()); + } + } + + public FunctionDeclaration MacroReplaceType(string toFind, string replaceWith, bool skipThisArgument) + { + var newFunc = new FunctionDeclaration(this); + if (!TypeSpec.IsNullOrEmptyTuple(newFunc.ReturnTypeSpec)) + { + newFunc.ReturnTypeName = newFunc.ReturnTypeSpec.ReplaceName(toFind, replaceWith).ToString(); + } + for (int i = 0; i < newFunc.ParameterLists.Last().Count; i++) + { + var arg = newFunc.ParameterLists.Last()[i]; + if (skipThisArgument && arg.PublicName == "this") + continue; + arg.TypeSpec = arg.TypeSpec.ReplaceName(toFind, replaceWith); + } + return newFunc; + } + + internal string ParametersToString() + { + var builder = new StringBuilder(); + var first = true; + foreach (var parm in ParameterLists.Last()) + { + if (!first) + { + builder.Append(", "); + } + else + { + first = false; + } + // forms + // public_name private_name: [inout] Type + // public_name: [inout] Type + // _ private_name: [inout] Type + if (parm.PublicName == parm.PrivateName) + { + builder.Append(parm.PublicName); + } + else if (parm.NameIsRequired) + { + builder.Append(parm.PublicName).Append(" ").Append(parm.PrivateName); + } + else + { + builder.Append("_ ").Append(parm.PrivateName); + } + builder.Append(": "); + if (parm.IsInOut || parm.TypeSpec.IsInOut) + builder.Append("inout "); + builder.Append(parm.TypeSpec); + } + return builder.ToString(); + } + + public override string ToString() + { + // Forms: + // access [modfiers] var Name: Type { [get | set] } [throws] + // access [modifiers] subscript Name [ args ]: Type { get [set] } [throws] + // access [modifiers] Name(args) -> Type [throws] + + var builder = new StringBuilder(); + builder.Append(Access).Append(" "); + if (IsFinal) + builder.Append("final "); + if (IsStatic) + builder.Append("static "); + + + if (IsProperty) + { + if (IsSubscript) + { + builder.Append(Parent.ToString()).Append(".subscript"); + builder.Append(" [").Append(ParametersToString()).Append("] -> "); + } + else + { + builder.Append("var ").Append(Parent.ToString()).Append(".").Append(PropertyName); + builder.Append(": "); + } + builder.Append(ReturnTypeName).Append(" { ").Append(PropertyKindString).Append(" }"); + if (HasThrows) + { + builder.Append(" throws"); + } + } + else + { + builder.Append(base.ToString()); + builder.Append(" (").Append(ParametersToString()).Append(")"); + if (HasThrows) + { + builder.Append(" throws"); + } + + builder.Append(" -> "); + if (TypeSpec.IsNullOrEmptyTuple(ReturnTypeSpec)) + { + builder.Append("()"); + } + else + { + builder.Append(ReturnTypeSpec); + } + } + return builder.ToString(); + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/GenericDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/GenericDeclaration.cs new file mode 100644 index 000000000000..0e2a8cf3a15e --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/GenericDeclaration.cs @@ -0,0 +1,143 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Linq; +using System.Collections.Generic; +using System.Xml.Linq; +using SwiftReflector.TypeMapping; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class GenericDeclaration + { + public GenericDeclaration() + { + Constraints = new List(); + } + + public GenericDeclaration(string name) + : this() + { + Name = name; + } + + public GenericDeclaration(GenericDeclaration other) + : this() + { + Name = other.Name; + foreach (var constraint in other.Constraints) + { + Constraints.Add(BaseConstraint.CopyOf(constraint)); + } + } + + + public string Name { get; set; } + public List Constraints { get; private set; } + + public bool IsProtocolConstrained(TypeMapper mapper) + { + if (Constraints.Count == 0) + return false; + foreach (BaseConstraint bc in Constraints) + { + Entity ent = null; + InheritanceConstraint inh = bc as InheritanceConstraint; + if (inh != null) + { + ent = mapper.GetEntityForTypeSpec(inh.InheritsTypeSpec); + } + else + { + EqualityConstraint eq = (EqualityConstraint)bc; + ent = mapper.GetEntityForTypeSpec(eq.Type2Spec); + } + if (ent == null) + continue; // shouldn't happen + if (ent.EntityType != EntityType.Protocol) + return false; + } + return true; + } + + public bool IsAssociatedTypeProtocolConstrained(TypeMapper mapper) + { + if (Constraints.Count == 0) + return false; + foreach (BaseConstraint bc in Constraints) + { + Entity ent = null; + InheritanceConstraint inh = bc as InheritanceConstraint; + if (inh != null) + { + ent = mapper.GetEntityForTypeSpec(inh.InheritsTypeSpec); + } + else + { + EqualityConstraint eq = (EqualityConstraint)bc; + ent = mapper.GetEntityForTypeSpec(eq.Type2Spec); + } + if (ent == null) + continue; // shouldn't happen + if (ent.EntityType != EntityType.Protocol) + return false; + if (ent.Type is ProtocolDeclaration proto && !proto.IsExistential) + return true; + } + return false; + } + + public bool IsClassConstrained(TypeMapper mapper) + { + if (Constraints.Count == 0) + return false; + foreach (BaseConstraint bc in Constraints) + { + Entity ent = null; + InheritanceConstraint inh = bc as InheritanceConstraint; + if (inh != null) + { + ent = mapper.GetEntityForTypeSpec(inh.InheritsTypeSpec); + } + else + { + EqualityConstraint eq = (EqualityConstraint)bc; + ent = mapper.GetEntityForTypeSpec(eq.Type2Spec); + } + if (ent == null) + continue; // shouldn't happen + if (ent.EntityType == EntityType.Class) + return true; + } + return false; + + } + + public static List FromXElement(TypeAliasFolder folder, XElement generic) + { + List decls = new List(); + if (generic == null) + return decls; + decls.AddRange(from decl in generic.Descendants("param") select new GenericDeclaration((string)decl.Attribute("name"))); + + var constraints = from constr in generic.Descendants("where") select BaseConstraint.FromXElement(folder, constr); + foreach (BaseConstraint constr in constraints) + { + GenericDeclaration decl = FindGenericDeclFor(constr, decls); + if (decl != null) + decl.Constraints.Add(constr); + } + + return decls; + } + + static GenericDeclaration FindGenericDeclFor(BaseConstraint constraint, List decls) + { + string nameToMatch = constraint.EffectiveTypeName(); + if (nameToMatch == null) + return null; + return decls.FirstOrDefault(d => d.Name == nameToMatch); + } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/GenericDeclarationCollection.cs b/src/SwiftReflector/src/SwiftXmlReflection/GenericDeclarationCollection.cs new file mode 100644 index 000000000000..bcbe5a14093e --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/GenericDeclarationCollection.cs @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class GenericDeclarationCollection : List, IXElementConvertible + { + public GenericDeclarationCollection() + : base() + { + } + + public GenericDeclarationCollection(int capacity) + : base(capacity) + { + } + + public XElement ToXElement() + { + if (Count == 0) + return null; + XElement genparms = new XElement("genericparameters"); + + foreach (GenericDeclaration decl in this) + { + XElement param = new XElement("param", new XAttribute("name", decl.Name)); + genparms.Add(param); + } + foreach (GenericDeclaration decl in this) + { + if (decl.Constraints.Count > 0) + { + foreach (BaseConstraint bc in decl.Constraints) + { + XElement bcel = bc.ToXElement(); + if (bcel != null) + genparms.Add(bcel); + } + } + } + return genparms; + } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/GenericReferenceAssociatedTypeProtocol.cs b/src/SwiftReflector/src/SwiftXmlReflection/GenericReferenceAssociatedTypeProtocol.cs new file mode 100644 index 000000000000..d1f063536ad8 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/GenericReferenceAssociatedTypeProtocol.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SwiftReflector.SwiftXmlReflection +{ + public class GenericReferenceAssociatedTypeProtocol + { + public NamedTypeSpec GenericPart { get; set; } + public ProtocolDeclaration Protocol { get; set; } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/IXElementConvertible.cs b/src/SwiftReflector/src/SwiftXmlReflection/IXElementConvertible.cs new file mode 100644 index 000000000000..e20d3ee015ce --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/IXElementConvertible.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Xml.Linq; + +namespace SwiftReflector +{ + public interface IXElementConvertible + { + XElement ToXElement(); + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/Inheritance.cs b/src/SwiftReflector/src/SwiftXmlReflection/Inheritance.cs new file mode 100644 index 000000000000..a35ece2c1818 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/Inheritance.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SwiftReflector.ExceptionTools; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class Inheritance : IXElementConvertible + { + public Inheritance(string inheritedTypeName, InheritanceKind inheritanceKind) + { + this.InheritanceKind = inheritanceKind; + InheritedTypeName = inheritedTypeName; + } + + public InheritanceKind InheritanceKind { get; private set; } + + string inheritedTypeName; + public string InheritedTypeName + { + get { return inheritedTypeName; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + inheritedTypeName = value; + try + { + InheritedTypeSpec = TypeSpecParser.Parse(inheritedTypeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 7, $"Unable to parse type name '{inheritedTypeName}': {ex.Message}"); + } + } + } + public TypeSpec InheritedTypeSpec { get; private set; } + + public static Inheritance FromXElement(TypeAliasFolder folder, XElement elem) + { + string typeName = (string)elem.Attribute("type"); + string inheritanceKindStr = (string)elem.Attribute("inheritanceKind"); + InheritanceKind kind = ToInheritanceKind(inheritanceKindStr); + var inheritance = new Inheritance(typeName, kind); + inheritance.InheritedTypeSpec = folder.FoldAlias(null, inheritance.InheritedTypeSpec); + return inheritance; + } + + public XElement ToXElement() + { + return new XElement("inherit", new XAttribute("type", InheritedTypeName), + new XAttribute("inheritanceKind", ToString(InheritanceKind))); + } + + static string ToString(InheritanceKind kind) + { + switch (kind) + { + case InheritanceKind.Class: + return "class"; + case InheritanceKind.Protocol: + return "protocol"; + default: + throw new ArgumentOutOfRangeException(nameof(kind)); + } + } + + static InheritanceKind ToInheritanceKind(string kindStr) + { + ArgumentNullException.ThrowIfNull(kindStr, nameof(kindStr)); + switch (kindStr) + { + case "protocol": + return InheritanceKind.Protocol; + case "class": + return InheritanceKind.Class; + default: + throw new ArgumentOutOfRangeException(nameof(kindStr), String.Format("Expected either protocol or class, but got {0}.", + kindStr)); + } + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/Member.cs b/src/SwiftReflector/src/SwiftXmlReflection/Member.cs new file mode 100644 index 000000000000..82a9c3d3fff8 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/Member.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Xml.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + public abstract class Member : BaseDeclaration, IXElementConvertible + { + protected Member() + : base() + { + } + + protected Member(Member other) + : base(other) + { + } + + public bool IsProtocolMember { get { return Parent != null && Parent is ProtocolDeclaration; } } + + #region IXElementConvertible implementation + + public XElement ToXElement() + { + return MakeXElement(); + } + + protected virtual XElement MakeXElement() + { + throw new NotImplementedException(); + } + #endregion + + public abstract bool HasDynamicSelf + { + get; + } + + public abstract bool HasDynamicSelfInReturnOnly + { + get; + } + + public abstract bool HasDynamicSelfInArguments + { + get; + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/ModuleDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/ModuleDeclaration.cs new file mode 100644 index 000000000000..abcc5f5fd417 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/ModuleDeclaration.cs @@ -0,0 +1,215 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using SwiftReflector.TypeMapping; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class ModuleDeclaration + { + public ModuleDeclaration() + { + Declarations = new List(); + Extensions = new List(); + Operators = new List(); + TypeAliases = new List(); + } + + public ModuleDeclaration(string name) + : this() + { + Name = name; + } + + public string Name { get; set; } + public bool IsUnrooted { get; private set; } + + public ModuleDeclaration MakeUnrooted() + { + if (IsUnrooted) + return this; + ModuleDeclaration unrooted = new ModuleDeclaration(); + unrooted.IsUnrooted = true; + unrooted.Name = Name; + return unrooted; + } + + public List Declarations { get; set; } + public List TypeAliases { get; private set; } + + public static ModuleDeclaration FromXElement(XElement elem, TypeDatabase typeDatabase) + { + ModuleDeclaration decl = new ModuleDeclaration + { + Name = (string)elem.Attribute("name"), + SwiftCompilerVersion = new Version((string)elem.Attribute("swiftVersion") ?? "3.1") + }; + + decl.TypeAliases.AddRange(elem.Descendants("typealias").Select(al => TypeAliasDeclaration.FromXElement(decl.Name, al))); + var folder = new TypeAliasFolder(decl.TypeAliases); + folder.AddDatabaseAliases(typeDatabase); + + // non extensions + foreach (var child in elem.Elements()) + { + if (child.Name == "extension") + { + decl.Extensions.Add(ExtensionDeclaration.FromXElement(folder, child, decl)); + } + else if (child.Name == "operator") + { + decl.Operators.Add(OperatorDeclaration.FromXElement(child, child.Attribute("moduleName")?.Value)); + } + else + { + decl.Declarations.Add(BaseDeclaration.FromXElement(folder, child, decl, null)); + } + } + return decl; + } + + public Version SwiftCompilerVersion { get; set; } + public bool IsEmpty() + { + return Declarations.Count == 0 && Extensions.Count == 0; + } + + public IEnumerable Classes { get { return Declarations.OfType().Where(cd => !(cd is ProtocolDeclaration)); } } + public IEnumerable Structs { get { return Declarations.OfType(); } } + public IEnumerable Enums { get { return Declarations.OfType(); } } + public IEnumerable Protocols { get { return Declarations.OfType(); } } + public IEnumerable Functions { get { return Declarations.OfType(); } } + public IEnumerable Properties { get { return Declarations.OfType(); } } + public IEnumerable TopLevelFunctions { get { return Functions.Where(f => f.Parent == null && f.Access == Accessibility.Public || f.Access == Accessibility.Open); } } + public IEnumerable TopLevelProperties { get { return Properties.Where(p => p.Parent == null && p.Access == Accessibility.Public || p.Access == Accessibility.Open); } } + public List Extensions { get; private set; } + public List Operators { get; private set; } + + + public bool IsCompilerCompatibleWith(Version targetCompilerVersion) + { + // yes, this could be an equality comparison, but I expect some + // level of backwards compatability at some point, so flesh it out now. + switch (SwiftCompilerVersion.Major) + { + case 2: + return false; // No. Just no. + case 3: + return targetCompilerVersion.Major == 3; + case 4: + return targetCompilerVersion.Major == 4; + case 5: + return targetCompilerVersion.Major == 5; + default: + return false; // not yet, thanks. + } + } + + public List AllClasses + { + get + { + return AllFooHelper(); + } + } + + public List AllStructs + { + get + { + return AllFooHelper(); + } + } + + public List AllEnums + { + get + { + return AllFooHelper(); + } + } + + public List AllProtocols + { + get + { + // no chicanery here - all protocol definitions are top-level + return Protocols.ToList(); + } + } + + List AllFooHelper() where T : TypeDeclaration + { + List ts = new List(); + AddAllInto(Classes, ts); + AddAllInto(Structs, ts); + AddAllInto(Enums, ts); + return ts; + } + + + void AddAllInto(IEnumerable someTypes, List repository) where T : TypeDeclaration + { + foreach (TypeDeclaration t in someTypes) + { + if (t is T) + repository.Add((T)t); + AddAllInto(t.InnerClasses, repository); + AddAllInto(t.InnerStructs, repository); + AddAllInto(t.InnerEnums, repository); + } + } + + + public List AllTypesAndTopLevelDeclarations + { + get + { + List decls = new List(); + AddAllDeclsInto(Declarations, decls); + return decls; + } + } + + void AddAllDeclsInto(IEnumerable someDecls, List allDecls) + { + foreach (BaseDeclaration d in someDecls) + { + allDecls.Add(d); + TypeDeclaration t = d as TypeDeclaration; + if (t != null) + { + AddAllDeclsInto(t.InnerClasses, allDecls); + AddAllDeclsInto(t.InnerStructs, allDecls); + AddAllDeclsInto(t.InnerEnums, allDecls); + } + } + } + + public List AllTypes + { + get + { + List types = new List(); + AddAllTypesInto(Declarations.OfType(), types); + return types; + } + } + + void AddAllTypesInto(IEnumerable someTypes, List allTypes) + { + foreach (TypeDeclaration t in someTypes) + { + allTypes.Add(t); + AddAllTypesInto(t.InnerClasses, allTypes); + AddAllTypesInto(t.InnerStructs, allTypes); + AddAllTypesInto(t.InnerEnums, allTypes); + } + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/OperatorDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/OperatorDeclaration.cs new file mode 100644 index 000000000000..07b8bb2ea0b4 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/OperatorDeclaration.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Xml.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class OperatorDeclaration + { + public OperatorDeclaration() + { + } + + public string ModuleName { get; private set; } + public string Name { get; private set; } + public OperatorType OperatorType { get; private set; } + public string PrecedenceGroup { get; private set; } + + public XElement ToXElement() + { + var xobjects = new List(); + GatherXObjects(xobjects); + XElement typeDecl = new XElement("operator", xobjects.ToArray()); + return typeDecl; + } + + void GatherXObjects(List xobjects) + { + xobjects.Add(new XAttribute("name", Name)); + if (PrecedenceGroup != null) + xobjects.Add(new XAttribute("precedenceGroup", PrecedenceGroup)); + xobjects.Add(new XAttribute("operatorKind", OperatorType.ToString())); + } + + public static OperatorDeclaration FromXElement(XElement elem, string module) + { + return new OperatorDeclaration() + { + ModuleName = module ?? elem.Attribute("moduleName")?.Value ?? "", + Name = elem.Attribute("name").Value, + PrecedenceGroup = NullOnNullOrEmpty(elem.Attribute("precedenceGroup")?.Value), + OperatorType = FunctionDeclaration.OperatorTypeFromElement((string)elem.Attribute("operatorKind")) + }; + } + + static string NullOnNullOrEmpty(string s) + { + return String.IsNullOrEmpty(s) ? null : s; + } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/ParameterItem.cs b/src/SwiftReflector/src/SwiftXmlReflection/ParameterItem.cs new file mode 100644 index 000000000000..7b934707af79 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/ParameterItem.cs @@ -0,0 +1,236 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using SwiftReflector.ExceptionTools; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class ParameterItem : IXElementConvertible + { + public static string kInOutMarker = "inout "; + public ParameterItem() + { + } + + public ParameterItem(ParameterItem pi) + { + PublicName = pi.PublicName; + PrivateName = pi.PrivateName; + TypeName = pi.TypeName; + IsInOut = pi.IsInOut; + IsVariadic = pi.IsVariadic; + } + + public string PublicName { get; set; } + public string PrivateName { get; set; } + public bool NameIsRequired { get { return !String.IsNullOrEmpty(PublicName); } } + public bool IsVariadic { get; set; } + + string typeName; + public string TypeName + { + get { return typeName; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + typeName = value; + try + { + typeSpec = TypeSpecParser.Parse(typeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 2, $"Unable to parse type name '{typeName}': {ex.Message}"); + } + } + } + TypeSpec typeSpec; + public TypeSpec TypeSpec + { + get { return typeSpec; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + typeSpec = value; + typeName = value.ToString(); + } + } + public bool IsInOut { get; set; } + + #region IXElementConvertible implementation + + public XElement ToXElement() + { + return new XElement("parameter", + new XAttribute("publicName", PublicName), + new XAttribute("privateName", PrivateName), + new XAttribute("type", TypeName), + new XAttribute("isVariadic", IsVariadic) + ); + } + + #endregion + + public static List> ParameterListListFromXElement(TypeAliasFolder folder, XElement elem) + { + var plists = from plelem in elem.Elements("parameterlist") + orderby (int)plelem.Attribute("index") + select ParameterListFromXElement(folder, plelem); + return plists.ToList(); + } + + public static List ParameterListFromXElement(TypeAliasFolder folder, XElement elem) + { + var indexed = from pelem in elem.Elements("parameter") + orderby (int)pelem.Attribute("index") + select ParameterItem.FromXElement(folder, pelem); + + return indexed.ToList(); + } + + public static ParameterItem FromXElement(TypeAliasFolder folder, XElement elem) + { + ParameterItem pi = new ParameterItem + { + PublicName = (string)elem.Attribute("publicName"), + PrivateName = (string)elem.Attribute("privateName"), + TypeName = (string)elem.Attribute("type"), + IsVariadic = elem.BoolAttribute("isVariadic"), + }; + pi.IsInOut = pi.TypeSpec.IsInOut; + pi.TypeSpec = folder.FoldAlias(null, pi.TypeSpec); + return pi; + } + + public bool EqualsIgnoreName(ParameterItem other) + { + if (other == null) + return false; + return IsVariadic == other.IsVariadic && this.TypeSpec.Equals(other.TypeSpec); + } + + public bool EqualsIgnoreNamesPartialMatch(ParameterItem other) + { + if (other == null) + return false; + return this.TypeSpec.EqualsPartialMatch(other.TypeSpec); + } + + public static bool AreEqualIgnoreNames(IList pl1, IList pl2) + { + if (pl1.Count != pl2.Count) + return false; + for (int i = 0; i < pl1.Count; i++) + { + if (!pl1[i].EqualsIgnoreName(pl2[i])) + return false; + } + return true; + } + + public static bool AreEqualIgnoreNamesReferencesInvariant(FunctionDeclaration fn1, IList pl1, + FunctionDeclaration fn2, IList pl2, bool matchPartialNames) + { + if (pl1.Count != pl2.Count) + { + return false; + } + + for (int i = 0; i < pl1.Count; i++) + { + var p1 = SubstituteSelfFromParent(fn1, pl1[i]); + var p2 = SubstituteSelfFromParent(fn2, pl2[i]); + p1 = RecastAsReference(p1); + p2 = RecastAsReference(p2); + + + // Names invariant means TYPE names not parameter names + if (!ParameterNamesMatch(p1, p2)) + { + // we give a pass on matching "self". + // this is done because "self" is a keyword in swift + // and when matching a wrapper function, we can't call + // a parameter "self" but have to call it "thisN" where + // N is either an empty string or a number. + // This is because there might be a real parameter named "this" + // and we had to rename it. + // The end result is that we can't use a "this" test, but we + // can use a "self" test. + var parmName1 = p1.NameIsRequired ? p1.PublicName : p1.PrivateName; + var parmName2 = p2.NameIsRequired ? p2.PublicName : p2.PrivateName; + if (parmName1 != "self" && parmName2 != "self") + return false; + } + if (fn1.IsTypeSpecGeneric(p1)) + { + if (!fn2.IsTypeSpecGeneric(p2)) + return false; + continue; + } + if (!p1.EqualsIgnoreName(p2)) + { + if (matchPartialNames) + { + if (!p1.EqualsIgnoreNamesPartialMatch(p2)) + return false; + } + else + { + return false; + } + } + } + return true; + } + + static ParameterItem SubstituteSelfFromParent(FunctionDeclaration func, ParameterItem p) + { + if (func.Parent == null || !p.TypeSpec.HasDynamicSelf) + return p; + p = new ParameterItem(p); + p.TypeSpec = p.TypeSpec.ReplaceName("Self", func.Parent.ToFullyQualifiedNameWithGenerics()); + return p; + } + + static ParameterItem RecastAsReference(ParameterItem p) + { + if (p.IsInOut) + { + if (!p.TypeSpec.IsInOut) + p.TypeSpec.IsInOut = true; + return p; + } + if (p.TypeSpec is NamedTypeSpec && p.TypeSpec.ContainsGenericParameters) + { + NamedTypeSpec named = (NamedTypeSpec)p.TypeSpec; + // special case - turn UnsafePointer into inout T for matching purposes + if (named.Name == "Swift.UnsafePointer" || named.Name == "Swift.UnsafeMutablePointer") + { + p = new ParameterItem(p); + p.TypeSpec = p.TypeSpec.GenericParameters[0]; + p.IsInOut = true; + p.TypeSpec.IsInOut = true; + } + } + return p; + } + + static bool ParameterNamesMatch(ParameterItem p1, ParameterItem p2) + { + // parameters are considered matching if and only if their public names match. + // The following are all DISTINCT + // public func foo (a b: Int) { } + // public func foo (c b: Int) { } + // public func foo (b: Int) { } - the public name is b + // public func foo (_ b: Int) { } - the public name is null or empty + + return p1.PublicName == p2.PublicName; + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/PropertyDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/PropertyDeclaration.cs new file mode 100644 index 000000000000..64ef240aff3d --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/PropertyDeclaration.cs @@ -0,0 +1,198 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Xml.Linq; +using SwiftReflector.ExceptionTools; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class PropertyDeclaration : Member + { + public PropertyDeclaration() + { + } + + public PropertyDeclaration(PropertyDeclaration other) + : base(other) + { + TypeName = other.TypeName; + Storage = other.Storage; + IsStatic = other.IsStatic; + IsLet = other.IsLet; + IsDeprecated = other.IsDeprecated; + IsUnavailable = other.IsUnavailable; + IsOptional = other.IsOptional; + } + + string typeName; + public string TypeName + { + get + { + return typeName; + } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + typeName = value; + try + { + TypeSpec = TypeSpecParser.Parse(typeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 3, $"Unable to parse type name '{typeName}': {ex.Message}"); + } + } + } + public TypeSpec TypeSpec { get; private set; } + public StorageKind Storage { get; set; } + public bool IsStatic { get; set; } + public bool IsLet { get; set; } + public bool IsDeprecated { get; set; } + public bool IsUnavailable { get; set; } + public bool IsOptional { get; set; } + public bool IsAsync + { + get + { + var getter = GetGetter(); + return getter == null ? false : getter.IsAsync; + } + } + + public FunctionDeclaration GetGetter() + { + return SearchForPropertyAccessor(FunctionDeclaration.kPropertyGetterPrefix); + } + + public FunctionDeclaration GetSetter() + { + return SearchForPropertyAccessor(FunctionDeclaration.kPropertySetterPrefix); + } + + + FunctionDeclaration SearchForPropertyAccessor(string prefix) + { + var funcs = GetFunctionsToSearch(); + return funcs.FirstOrDefault(f => f.IsProperty && + f.IsStatic == IsStatic && + f.Name.StartsWith(prefix, StringComparison.Ordinal) && + (f.Name.Length == prefix.Length + Name.Length) && + string.CompareOrdinal(f.Name, prefix.Length, Name, 0, Name.Length) == 0); + } + + IEnumerable GetFunctionsToSearch() + { + if (Parent == null) + { + return Module.Functions; + } + else + { + TypeDeclaration parent = Parent as TypeDeclaration; + if (parent == null) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 4, $"Expected property parent to be a TypeDeclaration, but was a {Parent.GetType().Name}"); + } + return parent.Members.OfType(); + } + } + + public static PropertyDeclaration PropFromXElement(TypeAliasFolder folder, XElement elem, ModuleDeclaration module, BaseDeclaration parent) + { + var property = new PropertyDeclaration + { + Name = (string)elem.Attribute("name"), + Module = module, + Parent = parent, + Access = TypeDeclaration.AccessibilityFromString((string)elem.Attribute("accessibility")), + TypeName = (string)elem.Attribute("type"), + Storage = StorageKindFromString((string)elem.Attribute("storage")), + IsStatic = elem.BoolAttribute("isStatic"), + IsLet = elem.BoolAttribute("isLet"), + IsDeprecated = elem.BoolAttribute("isDeprecated"), + IsUnavailable = elem.BoolAttribute("isUnavailable"), + IsOptional = elem.BoolAttribute("isOptional") + + }; + + property.TypeSpec = folder.FoldAlias(parent, property.TypeSpec); + + return property; + } + + protected override XElement MakeXElement() + { + return new XElement("property", + new XAttribute("name", Name), + new XAttribute("accessibility", Access), + new XAttribute("type", TypeName), + new XAttribute("storage", Storage), + new XAttribute("isStatic", IsStatic), + new XAttribute("isLet", IsLet), + new XAttribute("isDeprecated", IsDeprecated), + new XAttribute("isUnavailable", IsUnavailable), + new XAttribute("isOptional", IsOptional) + ); + } + + public static StorageKind StorageKindFromString(string value) + { + if (value == null) + return StorageKind.Unknown; + StorageKind storage; + Enum.TryParse(value, out storage); + return storage; + } + + public override string ToString() + { + // Forms: + // access [modfiers] var Name: Type { [get | set] } [throws] + // access [modifiers] subscript Name [ args ]: Type { get [set] } [throws] + // access [modifiers] Name(args) -> Type [throws] + + var getter = GetGetter(); + var builder = new StringBuilder(); + builder.Append(Access).Append(" "); + if (IsStatic) + builder.Append("static "); + if (getter.IsSubscript) + { + builder.Append("subscript ").Append(base.ToString()); + builder.Append(" [").Append(getter.ParametersToString()).Append("]:"); + } + else + { + builder.Append("var ").Append(Parent.ToString()).Append(".").Append(getter.PropertyName); + builder.Append(": "); + } + + builder.Append(getter.ReturnTypeName); + if (GetSetter() != null) + { + builder.Append(" { get set }"); + } + else + { + builder.Append(" { get }"); + } + if (getter.HasThrows) + { + builder.Append(" throws"); + } + return builder.ToString(); + } + + public override bool HasDynamicSelf => this.TypeSpec.HasDynamicSelf; + public override bool HasDynamicSelfInReturnOnly => false; + public override bool HasDynamicSelfInArguments => HasDynamicSelf; + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/ProtocolDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/ProtocolDeclaration.cs new file mode 100644 index 000000000000..219f1c61fd27 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/ProtocolDeclaration.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class ProtocolDeclaration : ClassDeclaration + { + public ProtocolDeclaration() + { + Kind = TypeKind.Protocol; + AssociatedTypes = new List(); + } + + protected override TypeDeclaration UnrootedFactory() + { + return new ProtocolDeclaration(); + } + + protected override void GatherXObjects(List xobjects) + { + base.GatherXObjects(xobjects); + if (AssociatedTypes.Count <= 0) + return; + var assocTypes = new List(); + foreach (var assoc in AssociatedTypes) + { + var contents = new List(); + assoc.GatherXObjects(contents); + assocTypes.Add(new XElement("associatedtype", contents.ToArray())); + } + xobjects.Add(new XElement("associatedtypes", assocTypes.ToArray())); + } + + protected override void CompleteUnrooting(TypeDeclaration unrooted) + { + base.CompleteUnrooting(unrooted); + if (unrooted is ProtocolDeclaration pd) + { + pd.AssociatedTypes.AddRange(AssociatedTypes); + } + } + + public List AssociatedTypes { get; private set; } + + public bool HasAssociatedTypes => AssociatedTypes.Count > 0; + + public AssociatedTypeDeclaration AssociatedTypeNamed(string name) + { + return AssociatedTypes.FirstOrDefault(at => at.Name == name); + } + + public bool HasDynamicSelf + { + // you shouldn't cache this. This type is mutable, so that would be bad + get => Members.Any(m => m.HasDynamicSelf); + } + + public bool HasDynamicSelfInReturnOnly + { + get => Members.Any(m => m.HasDynamicSelfInReturnOnly) && !HasDynamicSelfInArguments; + } + + public bool HasDynamicSelfInArguments + { + get => Members.Any(m => m.HasDynamicSelfInArguments); + } + + public bool IsExistential + { + get => !(HasAssociatedTypes || HasDynamicSelfInArguments); + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/ShamDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/ShamDeclaration.cs new file mode 100644 index 000000000000..5297c2a5f887 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/ShamDeclaration.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SwiftReflector.ExceptionTools; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class ShamDeclaration : TypeDeclaration + { + public ShamDeclaration(string fullName, EntityType type) + { + fullUnrootedName = fullName; + Tuple modName = fullName.SplitModuleFromName(); + unrootedName = modName.Item2; + IsUnrooted = true; + TypeKind kind = TypeKind.Unknown; + switch (type) + { + case EntityType.Scalar: + kind = TypeKind.Struct; + break; + case EntityType.Class: + kind = TypeKind.Class; + break; + case EntityType.Struct: + kind = TypeKind.Struct; + break; + case EntityType.Enum: + case EntityType.TrivialEnum: + kind = TypeKind.Enum; + break; + default: + break; + } + Kind = kind; + Module = new ModuleDeclaration(); + Module.Name = modName.Item1; + } + + protected override void GatherXObjects(System.Collections.Generic.List xobjects) + { + throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 1, $"Attempt to serialize a sham type for {this.ToFullyQualifiedName(true)}. Likely this type was never fully realized."); + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/StructDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/StructDeclaration.cs new file mode 100644 index 000000000000..56d3709a434a --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/StructDeclaration.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SwiftReflector.SwiftXmlReflection +{ + public class StructDeclaration : TypeDeclaration + { + public StructDeclaration() + { + Kind = TypeKind.Struct; + } + + protected override TypeDeclaration UnrootedFactory() + { + return new StructDeclaration(); + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/SubscriptDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/SubscriptDeclaration.cs new file mode 100644 index 000000000000..be6c97f838ba --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/SubscriptDeclaration.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SwiftReflector.SwiftXmlReflection +{ + // this is a pseudo class. + public class SubscriptDeclaration + { + public SubscriptDeclaration(FunctionDeclaration getter, FunctionDeclaration setter, FunctionDeclaration materializer) + { + Getter = getter; + Setter = setter; + Materializer = materializer; + } + + public FunctionDeclaration Getter { get; set; } + public FunctionDeclaration Setter { get; set; } + public FunctionDeclaration Materializer { get; set; } + public bool IsAsync => Getter.IsAsync; + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/TypeAliasDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/TypeAliasDeclaration.cs new file mode 100644 index 000000000000..4629953e9199 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/TypeAliasDeclaration.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Xml.Linq; +using SyntaxDynamo; +using SwiftReflector.ExceptionTools; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class TypeAliasDeclaration + { + public TypeAliasDeclaration() + { + } + + public Accessibility Access { get; private set; } + + string typeName; + public string TypeName + { + get { return typeName; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + typeName = value; + if (typeName.IndexOf(':') >= 0) + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 12, $"typealias {value} has a generic constraint which is not supported"); + try + { + typeSpec = TypeSpecParser.Parse(typeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 11, $"Unable to parse typealias name '{value}': {ex.Message}"); + } + } + } + + TypeSpec typeSpec; + public TypeSpec TypeSpec + { + get { return typeSpec; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + typeSpec = value; + typeName = value.ToString(); + } + } + + string targetTypeName; + public string TargetTypeName + { + get { return targetTypeName; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + targetTypeName = value; + try + { + targetTypeSpec = TypeSpecParser.Parse(targetTypeName); + } + catch (RuntimeException ex) + { + throw ErrorHelper.CreateError(ReflectorError.kReflectionErrorBase + 11, $"Unable to parse typealias target name '{value}': {ex.Message}"); + } + } + } + + TypeSpec targetTypeSpec; + public TypeSpec TargetTypeSpec + { + get { return targetTypeSpec; } + set + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + targetTypeSpec = value; + targetTypeName = value.ToString(); + } + } + + public String ModuleName + { + get + { + var spec = TypeSpec as NamedTypeSpec; + return spec?.Module; + } + } + + public XElement ToXElement() + { + return new XElement("typealias", new XAttribute("name", TypeName), + new XAttribute("type", TargetTypeName)); + } + + public static TypeAliasDeclaration FromXElement(string moduleName, XElement element) + { + var aliasName = element.Attribute("name").Value; + if (!aliasName.Contains(".")) + { + ArgumentNullException.ThrowIfNull(moduleName, nameof(moduleName)); + aliasName = $"{moduleName}.{aliasName}"; + } + return new TypeAliasDeclaration() + { + Access = TypeDeclaration.AccessibilityFromString((string)element.Attribute("accessibility")), + TypeName = aliasName, + TargetTypeName = element.Attribute("type").Value + }; + } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/TypeAliasFolder.cs b/src/SwiftReflector/src/SwiftXmlReflection/TypeAliasFolder.cs new file mode 100644 index 000000000000..79391dac91bc --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/TypeAliasFolder.cs @@ -0,0 +1,288 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SwiftReflector.TypeMapping; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class TypeAliasFolder + { + Dictionary aliases; + + public TypeAliasFolder(IList aliases) + { + this.aliases = new Dictionary(); + foreach (var alias in aliases) + { + this.aliases.Add(AliasKey(alias.TypeSpec), alias); + } + } + + public void AddDatabaseAliases(TypeDatabase typeDatabase) + { + if (typeDatabase == null) + return; + foreach (var moduleName in typeDatabase.ModuleNames) + { + var moduleDB = typeDatabase.ModuleDatabaseForModuleName(moduleName); + foreach (var alias in moduleDB.TypeAliases) + { + this.aliases.Add(AliasKey(alias.TypeSpec), alias); + } + } + } + + public TypeSpec FoldAlias(BaseDeclaration context, TypeSpec original) + { + if (aliases.Count == 0) + return original; + + var changed = false; + while (true) + { + original = FoldAlias(context, original, out changed); + if (!changed) + return original; + } + } + + TypeSpec FoldAlias(BaseDeclaration context, TypeSpec spec, out bool changed) + { + switch (spec.Kind) + { + case TypeSpecKind.Named: + return FoldAlias(context, spec as NamedTypeSpec, out changed); + case TypeSpecKind.Closure: + return FoldAlias(context, spec as ClosureTypeSpec, out changed); + case TypeSpecKind.ProtocolList: + return FoldAlias(context, spec as ProtocolListTypeSpec, out changed); + case TypeSpecKind.Tuple: + return FoldAlias(context, spec as TupleTypeSpec, out changed); + default: + throw new ArgumentOutOfRangeException(nameof(spec)); + } + + } + + TypeSpec FoldAlias(BaseDeclaration context, TupleTypeSpec spec, out bool changed) + { + changed = false; + TypeSpec[] newContents = spec.Elements.ToArray(); + for (int i = 0; i < newContents.Length; i++) + { + var elemChanged = false; + newContents[i] = FoldAlias(context, newContents[i], out elemChanged); + changed = changed || elemChanged; + } + if (changed) + { + var newTuple = new TupleTypeSpec(newContents); + newTuple.Attributes.AddRange(spec.Attributes); + return newTuple; + } + return spec; + } + + TypeSpec FoldAlias(BaseDeclaration context, ClosureTypeSpec spec, out bool changed) + { + var returnChanged = false; + var returnSpec = FoldAlias(context, spec.ReturnType, out returnChanged); + + var argsChanged = false; + var args = FoldAlias(context, spec.Arguments, out argsChanged); + + changed = returnChanged || argsChanged; + if (changed) + { + var newSpec = new ClosureTypeSpec(args, returnSpec); + newSpec.Attributes.AddRange(spec.Attributes); + return newSpec; + } + return spec; + } + + TypeSpec FoldAlias(BaseDeclaration context, ProtocolListTypeSpec spec, out bool changed) + { + changed = false; + var protos = new NamedTypeSpec[spec.Protocols.Count]; + + var protoChanged = false; + var i = 0; + foreach (var proto in spec.Protocols.Keys) + { + protos[i] = FoldAlias(context, proto, out protoChanged) as NamedTypeSpec; + changed = changed || protoChanged; + } + if (changed) + { + var newProtoList = new ProtocolListTypeSpec(protos); + newProtoList.Attributes.AddRange(spec.Attributes); + return newProtoList; + } + return spec; + } + + TypeSpec FoldAlias(BaseDeclaration context, NamedTypeSpec spec, out bool changed) + { + if (context == null || !context.IsTypeSpecGenericReference(spec)) + { + TypeAliasDeclaration decl = null; + if (aliases.TryGetValue(spec.Name, out decl)) + { + changed = true; + var newNamedSpec = RemapAliasedTypeSpec(spec, decl); + newNamedSpec.Attributes.AddRange(spec.Attributes); + return newNamedSpec; + } + else + { + return FoldGenerics(context, spec, out changed); + } + } + else + { + return FoldGenerics(context, spec, out changed); + } + } + + TypeSpec FoldGenerics(BaseDeclaration context, NamedTypeSpec spec, out bool changed) + { + changed = false; + if (!spec.ContainsGenericParameters) + return spec; + var genericsChanged = false; + var newGenerics = spec.GenericParameters.ToArray(); + for (int i = 0; i < newGenerics.Length; i++) + { + var genericChanged = false; + newGenerics[i] = FoldAlias(context, newGenerics[i], out genericChanged); + genericsChanged = genericsChanged || genericChanged; + } + if (genericsChanged) + { + changed = true; + var newNamedSpec = new NamedTypeSpec(spec.Name, newGenerics); + newNamedSpec.Attributes.AddRange(spec.Attributes); + return newNamedSpec; + } + return spec; + } + + TypeSpec RemapAliasedTypeSpec(NamedTypeSpec source, TypeAliasDeclaration decl) + { + // OK - in the Decl, we're going to have something like: + // Name = SomeOtherType + // or we'll have + // Name = SomeOtherType + // The first case is easy. In the second case we need to look + // at the t1 and find out where it comes from in Name<...> + // and remap it using what was provided in the source. + // But of course this get complicated. + // You could have something like this: + // typealias Foo = UnsafeMutablePointer<(Int, T)> + // So we need a map from each generic argument in Foo to + // each generic argument in source. + // Then we need to build a new TypeSpec using the declaration's target + // type substituting in elements from the map. + // and it gets more complicated because the thing we're looking at may + // be an associated type. + // + // Here's an example: + //public protocol KVPish + //{ + // associatedtype Key : Hashable + // associatedtype Value + // func contains(a: Key) -> Bool + // func get(a: Key) -> Value + //} + // + //public typealias KPHolder = Dictionary + var genericMap = new Dictionary(); + if (decl.TypeSpec.ContainsGenericParameters) + { + for (int i = 0; i < decl.TypeSpec.GenericParameters.Count; i++) + { + // the "parts" here are part of a formal generic declaration + // and they HAVE to be named type specs and they themselves + // won't ever be generic. They're going to just be a name. + // Future Steve: trust me. + var part = decl.TypeSpec.GenericParameters[i] as NamedTypeSpec; + genericMap.Add(part.Name, source.GenericParameters[i]); + } + } + return RemapTypeSpec(decl.TargetTypeSpec, genericMap); + } + + TypeSpec RemapTypeSpec(TypeSpec spec, Dictionary nameMap) + { + switch (spec.Kind) + { + case TypeSpecKind.Closure: + return RemapTypeSpec(spec as ClosureTypeSpec, nameMap); + case TypeSpecKind.Named: + return RemapTypeSpec(spec as NamedTypeSpec, nameMap); + case TypeSpecKind.ProtocolList: + return RemapTypeSpec(spec as ProtocolListTypeSpec, nameMap); + case TypeSpecKind.Tuple: + return RemapTypeSpec(spec as TupleTypeSpec, nameMap); + default: + throw new NotImplementedException($"Unknown type spec kind {spec.Kind}"); + } + } + + TypeSpec RemapTypeSpec(TupleTypeSpec tuple, Dictionary nameMap) + { + var tupleElems = tuple.Elements.ToArray(); + for (int i = 0; i < tupleElems.Length; i++) + { + tupleElems[i] = RemapTypeSpec(tupleElems[i], nameMap); + } + return new TupleTypeSpec(tupleElems); + } + + TypeSpec RemapTypeSpec(ClosureTypeSpec clos, Dictionary nameMap) + { + var returnType = RemapTypeSpec(clos.ReturnType, nameMap); + var args = RemapTypeSpec(clos.Arguments, nameMap); + return new ClosureTypeSpec(args, returnType); + } + + TypeSpec RemapTypeSpec(ProtocolListTypeSpec proto, Dictionary nameMap) + { + return new ProtocolListTypeSpec(proto.Protocols.Keys.Select(k => RemapTypeSpec(k, nameMap) as NamedTypeSpec)); + } + + TypeSpec RemapTypeSpec(NamedTypeSpec named, Dictionary nameMap) + { + var parts = named.Name.Split('.'); + for (int i = 0; i < parts.Length; i++) + { + TypeSpec replacement; + if (nameMap.TryGetValue(parts[i], out replacement)) + { + parts[i] = replacement.ToString(); + } + } + var newName = parts.InterleaveStrings("."); + if (named.ContainsGenericParameters) + { + var newParams = named.GenericParameters.Select(p => RemapTypeSpec(p, nameMap)).ToArray(); + return new NamedTypeSpec(newName, newParams); + } + else + { + return new NamedTypeSpec(newName); + } + } + + static string AliasKey(TypeSpec spec) + { + if (spec is NamedTypeSpec named) + return named.Name; + return spec.ToString(); + } + } +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/TypeDeclaration.cs b/src/SwiftReflector/src/SwiftXmlReflection/TypeDeclaration.cs new file mode 100644 index 000000000000..dc19bf211b7a --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/TypeDeclaration.cs @@ -0,0 +1,581 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using SwiftReflector.ExceptionTools; +using SwiftReflector.TypeMapping; +using System.Text; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class TypeDeclaration : BaseDeclaration, IXElementConvertible + { + public TypeDeclaration() + : base() + { + Kind = TypeKind.Unknown; + InnerClasses = new List(); + InnerStructs = new List(); + InnerEnums = new List(); + Members = new List(); + Inheritance = new List(); + TypeAliases = new List(); + } + + public TypeKind Kind { get; set; } + public List Inheritance { get; set; } + public List Members { get; set; } + public List InnerClasses { get; set; } + public List InnerStructs { get; set; } + public List InnerEnums { get; set; } + public List TypeAliases { get; set; } + public bool IsObjC { get; set; } + public bool IsFinal { get; set; } + public bool IsDeprecated { get; set; } + public bool IsUnavailable { get; set; } + public bool IsUnrooted { get; protected set; } + + public TypeDeclaration MakeUnrooted() + { + if (IsUnrooted) + return this; + + TypeDeclaration unrooted = UnrootedFactory(); + unrooted.unrootedName = ToFullyQualifiedName(false); + unrooted.fullUnrootedName = ToFullyQualifiedName(true); + unrooted.Kind = Kind; + unrooted.Inheritance.AddRange(Inheritance); + unrooted.Members.AddRange(Members); + unrooted.IsObjC = IsObjC; + unrooted.IsFinal = IsFinal; + unrooted.IsUnrooted = true; + unrooted.Name = Name; + unrooted.Access = Access; + unrooted.Module = Module.MakeUnrooted(); + unrooted.Generics.AddRange(Generics); + CompleteUnrooting(unrooted); + return unrooted; + } + + protected virtual TypeDeclaration UnrootedFactory() + { + throw new NotImplementedException(); + } + + public bool IsObjCOrInheritsObjC(TypeMapper typeMapper) + { + if (IsObjC) + return true; + if (Inheritance == null || Inheritance.Count == 0) + return false; + foreach (var inheritance in Inheritance) + { + if (inheritance.InheritanceKind != InheritanceKind.Class) + continue; + var entity = typeMapper.GetEntityForTypeSpec(inheritance.InheritedTypeSpec); + if (entity == null) + throw ErrorHelper.CreateError(ReflectorError.kCompilerBase + 4, $"Unable to find entity for class inheritance type {inheritance.InheritedTypeName}"); + return entity.Type.IsObjC || entity.Type.IsObjCOrInheritsObjC(typeMapper); + } + return false; + } + + public bool IsSwiftBaseClass() + { + // this predicate determines if a TypeDeclaration is: + // * a ClassDeclaration + // * an all swift object + // * no inheritance or any inheritance is not class inheritance + if (!(this is ClassDeclaration)) + return false; + if (IsObjC) + return false; + return Inheritance == null || !Inheritance.Any(inh => inh.InheritanceKind == InheritanceKind.Class); + } + + public bool ProtectedObjCCtorIsInThis(TypeMapper typeMapper) + { + // this predicate determines if this type has a protected objc ctor in this. + // it's used to determine if, when writing the C# binding, if we need to call base () or this () + var classDecl = this as ClassDeclaration; + if (classDecl == null) + return false; + if (!IsObjC) + return false; + // no inheritance + // this : (nothing) -> IsImportedBinding + if (Inheritance == null || Inheritance.FirstOrDefault(inh => inh.InheritanceKind == InheritanceKind.Class) == null) + { + // if there's no inheritance, then the protected ctor is in this if it wasn't imported + return !classDecl.IsImportedBinding; + } + // this : import -> true + // this : binding : binding : import -> false + var classInherit = Inheritance.First(inh => inh.InheritanceKind == InheritanceKind.Class); + var entity = typeMapper.GetEntityForTypeSpec(classInherit.InheritedTypeSpec); + if (entity == null) + throw ErrorHelper.CreateError(ReflectorError.kCompilerBase + 9, $"Unable to find entity for class inheritance on type {classInherit.InheritedTypeName}"); + var inheritedClass = entity.Type as ClassDeclaration; + if (inheritedClass == null) + throw ErrorHelper.CreateError(ReflectorError.kCompilerBase + 10, $"Expected a ClassDeclaration in inheritance chain but got {entity.Type.ToFullyQualifiedName(true)} of {entity.Type.GetType().Name}"); + return inheritedClass.IsImportedBinding; + } + + protected virtual void CompleteUnrooting(TypeDeclaration unrooted) + { + } + + protected string unrootedName = null; + protected string fullUnrootedName = null; + public override string ToFullyQualifiedName(bool includeModule = true) + { + if (IsUnrooted) + { + return includeModule ? fullUnrootedName : unrootedName; + } + else + { + return base.ToFullyQualifiedName(includeModule); + } + } + + #region IXElementConvertible implementation + + public XElement ToXElement() + { + if (!IsUnrooted) + throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 0, "TypeDeclarations must be unrooted to create from XML."); + + var xobjects = new List(); + GatherXObjects(xobjects); + XElement typeDecl = new XElement("typedeclaration", xobjects.ToArray()); + return typeDecl; + } + + protected virtual void GatherXObjects(List xobjects) + { + XElement generics = Generics.ToXElement(); + if (generics != null) + xobjects.Add(generics); + xobjects.Add(new XAttribute("kind", ToString(Kind))); + xobjects.Add(new XAttribute("name", fullUnrootedName)); + xobjects.Add(new XAttribute("module", Module.Name)); + xobjects.Add(new XAttribute("accessibility", TypeDeclaration.ToString(Access))); + xobjects.Add(new XAttribute("isObjC", IsObjC ? "true" : "false")); + xobjects.Add(new XAttribute("isFinal", IsFinal ? "true" : "false")); + xobjects.Add(new XAttribute("isDeprecated", IsDeprecated ? "true" : "false")); + xobjects.Add(new XAttribute("isUnavailable", IsUnavailable ? "true" : "false")); + // DO NOT INCLUDE Inner[Classes,Structs,Enums] + List memcontents = new List(Members.Select(m => m.ToXElement())); + xobjects.Add(new XElement("members", memcontents.ToArray())); + List inherits = new List(Inheritance.Select(i => i.ToXElement())); + xobjects.Add(new XElement("inherits", inherits.ToArray())); + if (TypeAliases.Count > 0) + { + var aliases = new List(TypeAliases.Select(a => a.ToXElement())); + xobjects.Add(new XElement("typealiases", aliases.ToArray())); + } + } + + #endregion + + public static TypeDeclaration TypeFromXElement(TypeAliasFolder folder, XElement elem, ModuleDeclaration module, BaseDeclaration parent /* can be null */) + { + var decl = FromKind((string)elem.Attribute("kind")); + bool isUnrooted = elem.Attribute("module") != null; + decl.Module = module; + decl.Parent = parent; + if (isUnrooted) + { + decl.IsUnrooted = true; + decl.fullUnrootedName = (string)elem.Attribute("name"); + decl.unrootedName = decl.fullUnrootedName.NameWithoutModule(); + decl.Name = decl.fullUnrootedName.Contains('.') ? decl.fullUnrootedName.Substring(decl.fullUnrootedName.LastIndexOf('.') + 1) + : decl.fullUnrootedName; + } + else + { + decl.Name = (string)elem.Attribute("name"); + } + decl.Access = AccessibilityFromString((string)elem.Attribute("accessibility")); + decl.IsObjC = elem.BoolAttribute("isObjC"); + decl.IsFinal = elem.BoolAttribute("isFinal"); + decl.IsDeprecated = elem.BoolAttribute("isDeprecated"); + decl.IsUnavailable = elem.BoolAttribute("isUnavailable"); + + decl.InnerClasses.AddRange(InnerFoo(folder, elem, "innerclasses", module, decl)); + decl.InnerStructs.AddRange(InnerFoo(folder, elem, "innerstructs", module, decl)); + decl.InnerEnums.AddRange(InnerFoo(folder, elem, "innerenums", module, decl)); + if (elem.Element("members") != null) + { + var members = from mem in elem.Element("members").Elements() + select Member.FromXElement(folder, mem, module, decl) as Member; + decl.Members.AddRange(members); + } + if (elem.Element("inherits") != null) + { + var inherits = from inherit in elem.Element("inherits").Elements() + select SwiftReflector.SwiftXmlReflection.Inheritance.FromXElement(folder, inherit) as Inheritance; + decl.Inheritance.AddRange(inherits); + } + var typealiases = elem.Element("typealiases"); + if (typealiases != null) + { + var aliases = from alias in typealiases.Elements() + select TypeAliasDeclaration.FromXElement(module.Name, alias); + decl.TypeAliases.AddRange(aliases); + } + EnumDeclaration edecl = decl as EnumDeclaration; + if (edecl != null) + { + var enumElements = (from enumElement in elem.Element("elements").Elements() + select new EnumElement((string)enumElement.Attribute("name"), (string)enumElement.Attribute("type"), + (long?)enumElement.Attribute("intValue"))).ToList(); ; + edecl.Elements.AddRange(enumElements); + if (elem.Attribute("rawType") != null) + { + var rawType = TypeSpecParser.Parse((string)elem.Attribute("rawType")); + edecl.RawTypeName = folder.FoldAlias(parent, rawType).ToString(); + } + } + + var protoDecl = decl as ProtocolDeclaration; + if (protoDecl != null) + { + if (elem.Element("associatedtypes") != null) + { + var assocElements = from assocElem in elem.Element("associatedtypes").Elements() + select AssociatedTypeDeclaration.FromXElement(folder, assocElem); + protoDecl.AssociatedTypes.AddRange(assocElements); + } + } + + return decl; + } + + static IEnumerable InnerFoo(TypeAliasFolder folder, XElement parent, string innerName, ModuleDeclaration module, BaseDeclaration parDecl) where T : TypeDeclaration + { + var inner = parent.Elements(innerName).SelectMany(el => el.Elements("typedeclaration")); + var innerList = inner.Select(elem => FromXElement(folder, elem, module, parDecl)).ToList(); + var innerCast = innerList.Cast().ToList(); + return innerCast; + } + + static TypeDeclaration FromKind(string kind) + { + switch (kind) + { + case "class": + return new ClassDeclaration(); + case "struct": + return new StructDeclaration(); + case "enum": + return new EnumDeclaration(); + case "protocol": + return new ProtocolDeclaration(); + default: + return new TypeDeclaration(); + } + } + + internal static string ToString(TypeKind kind) + { + switch (kind) + { + case TypeKind.Class: + return "class"; + case TypeKind.Struct: + return "struct"; + case TypeKind.Enum: + return "enum"; + case TypeKind.Protocol: + return "protocol:"; + default: + throw new ArgumentOutOfRangeException(nameof(kind)); + } + } + + public static Accessibility AccessibilityFromString(string value) + { + if (value == null) + return Accessibility.Unknown; + Accessibility access; + Enum.TryParse(value, out access); + return access; + } + + internal static string ToString(Accessibility access) + { + return access.ToString(); + } + + public List AllVirtualMethods() + { + if (this is ProtocolDeclaration) + { + return Members.OfType().Where(decl => + !decl.IsConstructorOrDestructor && + (!decl.IsFinal && !decl.IsStatic && decl.Access == Accessibility.Public)).ToList(); + } + else + { + return Members.OfType().Where(decl => + !decl.IsConstructorOrDestructor && + (!decl.IsFinal && !decl.IsStatic && decl.Access == Accessibility.Open)).ToList(); + } + } + + public List AllProperties() + { + return Members.OfType().ToList(); + } + + public List AllVirtualProperties() + { + Accessibility requiredAccessibility; + if (this is ProtocolDeclaration) + { + requiredAccessibility = Accessibility.Public; + } + else + { + requiredAccessibility = Accessibility.Open; + } + return Members.OfType().Where(decl => + { + if (decl.IsStatic) + return false; + if (decl.Access != requiredAccessibility) + return false; + var getter = decl.GetGetter(); + if (getter == null) + return false; + if (getter.IsDeprecated || getter.IsUnavailable) + return false; + return true; + }).ToList(); + } + + public List AllFinalMethods() + { + return Members.OfType().Where(decl => + !decl.IsConstructorOrDestructor && decl.IsFinal).ToList(); + } + + public List AllMethodsNoCDTor() + { + return Members.OfType().Where(decl => !decl.IsConstructorOrDestructor).ToList(); + } + + public List AllConstructors() + { + return Members.OfType().Where(decl => decl.IsConstructor).ToList(); + } + + public List AllDestructors() + { + return Members.OfType().Where(decl => decl.IsDestructor).ToList(); + } + + public List AllSubscripts() + { + var allSubFuncs = Members.OfType().Where(decl => decl.IsSubscript).ToList(); + var allSubs = new List(); + while (allSubFuncs.Count > 0) + { + int i = allSubFuncs.Count - 1; + FunctionDeclaration decl = allSubFuncs[i]; + allSubFuncs.RemoveAt(i); + if (decl.IsSubscriptMaterializer) + continue; + if (decl.IsSubscriptGetter) + { + FunctionDeclaration setter = GetAndRemoveSetter(allSubFuncs, decl); + FunctionDeclaration materializer = GetAndRemoveMaterializer(allSubFuncs, decl); + allSubs.Add(new SubscriptDeclaration(decl, setter, materializer)); + } + else if (decl.IsSubscriptSetter) + { + FunctionDeclaration getter = GetAndRemoveGetter(allSubFuncs, decl); + FunctionDeclaration materializer = GetAndRemoveMaterializer(allSubFuncs, decl); + allSubs.Add(new SubscriptDeclaration(getter, decl, materializer)); + } + } + return allSubs; + } + + public TypeSpec ToTypeSpec() + { + NamedTypeSpec ns = new NamedTypeSpec(ToFullyQualifiedName()); + ns.GenericParameters.AddRange(Generics.Select(gen => new NamedTypeSpec(gen.Name))); + return ns; + } + + static FunctionDeclaration GetAndRemoveMaterializer(List decls, FunctionDeclaration other) + { + // FIXME - materializers don't have enough to match on with 100% confidence + // Materializers are (probably) not needed by tom-swifty, so no big + return null; + } + + static FunctionDeclaration GetAndRemoveGetter(List decls, FunctionDeclaration other) + { + var plToMatch = new List(); + TypeSpec returnToMatch = null; + var selfToMatch = other.Parent; + + if (other.IsSetter) + { + // setter - + // The arguments to a setter are + // value, arg1, arg2 ... argn + // We want to match the type of the return of the getter to the value of the setter + // as well as the parameters + List pl = other.ParameterLists.Last(); + plToMatch.AddRange(pl.GetRange(1, pl.Count - 1)); + returnToMatch = pl[0].TypeSpec; + } + else + { + // materializer. + // The arguments to a materializer are + // buffer, callbackStoragebuffer, arg1, arg2 ... argn + // We have no return to match. Oops. + List pl = other.ParameterLists.Last(); + plToMatch.AddRange(pl.GetRange(2, pl.Count - 2)); + returnToMatch = null; + } + + + for (int i = 0; i < decls.Count; i++) + { + FunctionDeclaration getter = decls[i]; + if (getter.Parent != selfToMatch) + return null; + if (!getter.IsSubscriptGetter) + continue; + if ((returnToMatch != null && returnToMatch.Equals(getter.ReturnTypeSpec)) || returnToMatch == null) + { + List targetPl = getter.ParameterLists.Last(); + if (ParmsMatch(plToMatch, targetPl)) + { + decls.RemoveAt(i); + return getter; + } + } + } + return null; + } + + static FunctionDeclaration GetAndRemoveSetter(List decls, FunctionDeclaration other) + { + var plToMatch = new List(); + var selfToMatch = other.Parent; + + if (other.IsGetter) + { + // getter - + // The arguments to a getter are + // arg1, arg2 ... argn + // We want to match the type of the return of the getter to the value of the setter + // as well as the parameters + List pl = other.ParameterLists.Last(); + ParameterItem item = new ParameterItem(); + item.PublicName = ""; + item.PrivateName = "retval"; + item.TypeSpec = other.ReturnTypeSpec; + item.TypeName = other.ReturnTypeName; + plToMatch.Add(item); + plToMatch.AddRange(pl); + } + else + { + // we don't have enough information to match on setter + // and since we don't use the materializer, NBD. + + // materializer. + // The arguments to a materializer are + // buffer, callbackStoragebuffer, arg1, arg2 ... argn + // We have no return to match. Oops. + return null; + } + + for (int i = 0; i < decls.Count; i++) + { + FunctionDeclaration setter = decls[i]; + if (!setter.IsSubscriptGetter) + continue; + List targetPl = setter.ParameterLists.Last(); + if (ParmsMatch(plToMatch, targetPl)) + { + decls.RemoveAt(i); + return setter; + } + } + return null; + } + + public bool VirtualMethodExistsInInheritedBoundType(FunctionDeclaration func, TypeMapper typeMapper) + { + // virtual methods are only in classes + if (!(this is ClassDeclaration)) + return false; + var classInheritance = Inheritance.FirstOrDefault(inh => inh.InheritanceKind == InheritanceKind.Class); + if (classInheritance == null) + return false; + + var inheritedEntity = typeMapper.GetEntityForTypeSpec(classInheritance.InheritedTypeSpec); + if (inheritedEntity == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 18, $"Unable to find type database entry for class {classInheritance.InheritedTypeName} while searching inheritance."); + + // if we get here, the Type has to be a ClassDeclaration + var inheritedClass = inheritedEntity.Type as ClassDeclaration; + + var methods = inheritedClass.AllVirtualMethods().FindAll(fn => fn.Name == func.Name + && fn.ParameterLists.Last().Count == func.ParameterLists.Last().Count).ToList(); + foreach (var method in methods) + { + if (ParmsMatchWithNames(method.ParameterLists.Last(), func.ParameterLists.Last()) + && method.ReturnTypeSpec.Equals(func.ReturnTypeSpec)) + return true; + } + return inheritedClass.VirtualMethodExistsInInheritedBoundType(func, typeMapper); + } + + static bool ParmsMatchWithNames(List pl1, List pl2) + { + if (pl1.Count != pl2.Count) + return false; + for (int i = 0; i < pl1.Count; i++) + { + if (pl1[i].PublicName != pl2[i].PublicName) + return false; + if (pl1[i].IsInOut != pl2[i].IsInOut) + return false; + if (!pl1[i].TypeSpec.Equals(pl2[i].TypeSpec)) + return false; + } + return true; + } + + static bool ParmsMatch(List pl1, List pl2) + { + if (pl1.Count != pl2.Count) + return false; + for (int i = 0; i < pl1.Count; i++) + { + if (pl1[i].IsInOut != pl2[i].IsInOut) + return false; + if (!pl1[i].TypeSpec.Equals(pl2[i].TypeSpec)) + return false; + } + return true; + } + + + } + +} diff --git a/src/SwiftReflector/src/SwiftXmlReflection/TypeSpec.cs b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpec.cs new file mode 100644 index 000000000000..77f2f828242b --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpec.cs @@ -0,0 +1,889 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text; +using SwiftReflector.TypeMapping; +using System.Linq; +using System.Collections; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class TypeSpecAttribute + { + public TypeSpecAttribute(string name) + { + Name = name; + Parameters = new List(); + } + public string Name { get; set; } + public List Parameters { get; private set; } + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append('@'); + sb.Append(Name); + if (Parameters.Count > 0) + { + sb.Append('('); + for (int i = 0; i < Parameters.Count; i++) + { + if (i > 0) + sb.Append(", "); + sb.Append(Parameters[i]); + } + sb.Append(')'); + } + return sb.ToString(); + } + } + + public abstract class TypeSpec + { + protected TypeSpec(TypeSpecKind kind) + { + Kind = kind; + GenericParameters = new List(); + Attributes = new List(); + } + + public TypeSpecKind Kind { get; private set; } + public List GenericParameters { get; private set; } + public bool ContainsGenericParameters { get { return GenericParameters.Count != 0; } } + public List Attributes { get; private set; } + public bool HasAttributes { get { return Attributes.Count != 0; } } + public bool IsInOut { get; set; } + public bool IsAny { get; set; } + public virtual bool IsEmptyTuple { get { return false; } } + protected abstract string LLToString(bool useFullName); + protected virtual string LLFinalStringParts() { return ""; } + protected abstract bool LLEquals(TypeSpec other, bool partialNameMatch); + public string TypeLabel { get; set; } + public bool IsArray + { + get + { + NamedTypeSpec ns = this as NamedTypeSpec; + return ns != null && ns.Name == "Swift.Array"; + } + } + + public bool IsBoundGeneric(BaseDeclaration context, TypeMapper mapper) + { + switch (this.Kind) + { + case TypeSpecKind.Named: + NamedTypeSpec ns = (NamedTypeSpec)this; + Entity en = mapper.TryGetEntityForSwiftClassName(ns.Name); + if (en == null) + { + if (context.IsTypeSpecGeneric(ns)) + return false; // unbound + } + foreach (TypeSpec genParm in GenericParameters) + { + if (genParm.IsUnboundGeneric(context, mapper)) + return false; // unbound + } + return true; + case TypeSpecKind.Closure: + ClosureTypeSpec cs = (ClosureTypeSpec)this; + return cs.Arguments.IsBoundGeneric(context, mapper) && cs.ReturnType.IsBoundGeneric(context, mapper); + case TypeSpecKind.Tuple: + TupleTypeSpec ts = (TupleTypeSpec)this; + foreach (TypeSpec elem in ts.Elements) + { + if (elem.IsUnboundGeneric(context, mapper)) + return false; + } + return true; + default: + throw new NotSupportedException("unknown TypeSpecKind " + this.Kind.ToString()); + } + } + + public bool IsUnboundGeneric(BaseDeclaration context, TypeMapper mapper) + { + switch (Kind) + { + case TypeSpecKind.Named: + NamedTypeSpec ns = (NamedTypeSpec)this; + if (context.IsTypeSpecGeneric(ns.ToString())) + return true; + foreach (TypeSpec genparm in GenericParameters) + { + if (genparm.IsUnboundGeneric(context, mapper)) + return true; + } + return false; + case TypeSpecKind.Closure: + ClosureTypeSpec cs = (ClosureTypeSpec)this; + return cs.Arguments.IsUnboundGeneric(context, mapper) && cs.ReturnType.IsUnboundGeneric(context, mapper); + case TypeSpecKind.Tuple: + TupleTypeSpec ts = (TupleTypeSpec)this; + foreach (TypeSpec elem in ts.Elements) + { + if (elem.IsUnboundGeneric(context, mapper)) + return true; + } + return false; + case TypeSpecKind.ProtocolList: + return false; + default: + throw new NotSupportedException("unknown TypeSpecKind " + this.Kind.ToString()); + } + } + + + public override bool Equals(object obj) + { + TypeSpec spec = obj as TypeSpec; + if (spec == null) + return false; + if (Kind != spec.Kind) + return false; + if (!ListEqual(GenericParameters, spec.GenericParameters, false)) + return false; + if (IsInOut != spec.IsInOut) + return false; + // Don't compare IsAny - it's really not important (yet) + return LLEquals(spec, false); + } + + public bool EqualsPartialMatch(TypeSpec spec) + { + if (spec == null) + return false; + if (Kind != spec.Kind) + return false; + if (!ListEqual(GenericParameters, spec.GenericParameters, true)) + return false; + if (IsInOut != spec.IsInOut) + return false; + // Don't compare IsAny - it's really not important (yet) + return LLEquals(spec, true); + } + + public virtual bool EqualsReferenceInvaraint(TypeSpec type) + { + var a = ProjectAsNonReference(this); + var b = ProjectAsNonReference(type); + + if (b.Kind != a.Kind) + return false; + if (b.GetType() != a.GetType()) + return false; + // shouldn't do Name equality except in functions + return a.LLEquals(b, false); + } + + public TypeSpec NonReferenceCloneOf() + { + if (!IsInOut) + return this; + var ty = MemberwiseClone() as TypeSpec; + ty.IsInOut = false; + return ty; + } + + static TypeSpec ProjectAsNonReference(TypeSpec a) + { + if (a.IsInOut) + { + return a.NonReferenceCloneOf(); + } + var namedType = a as NamedTypeSpec; + if (namedType != null && namedType.GenericParameters.Count == 1) + { + if (namedType.Name == "Swift.UnsafePointer" || namedType.Name == "Swift.UnsafeMutablePointer") + return namedType.GenericParameters[0]; + } + return a; + } + + + public override int GetHashCode() + { + return ToString().GetHashCode(); + } + + protected static bool ListEqual(List one, List two, bool partialNameMatch) + { + if (one.Count != two.Count) + return false; + for (int i = 0; i < one.Count; i++) + { + if (partialNameMatch) + { + if (!one[i].EqualsPartialMatch(two[i])) + return false; + } + else + { + if (!one[i].Equals(two[i])) + return false; + } + } + return true; + } + + public static bool IsNullOrEmptyTuple(TypeSpec spec) + { + return spec == null || spec.IsEmptyTuple; + } + + public static bool BothNullOrEqual(TypeSpec one, TypeSpec two) + { + if (one == null && two == null) + return true; + if (one == null || two == null) + return false; + return one.Equals(two); + } + + public bool ContainsBoundGenericClosure() + { + return ContainsBoundGenericClosure(0); + } + + bool ContainsBoundGenericClosure(int depth) + { + if (this is NamedTypeSpec namedTypeSpec) + { + foreach (var subSpec in namedTypeSpec.GenericParameters) + { + if (subSpec.ContainsBoundGenericClosure(depth + 1)) + return true; + } + } + else if (this is TupleTypeSpec tupleSpec) + { + foreach (var subSpec in tupleSpec.Elements) + { + if (subSpec.ContainsBoundGenericClosure(depth + 1)) + return true; + } + } + else if (this is ClosureTypeSpec closureSpec) + { + return depth > 0; + } + return false; + } + + public override string ToString() + { + return ToString(true); + } + + public string ToString(bool useFullNames) + { + StringBuilder builder = new StringBuilder(); + + foreach (var attr in Attributes) + { + builder.Append(attr.ToString()); + builder.Append(' '); + } + if (IsInOut) + builder.Append("inout "); + + if (IsAny) + builder.Append("any "); + + if (TypeLabel != null) + { + builder.Append(TypeLabel).Append(": "); + } + builder.Append(LLToString(useFullNames)); + + if (ContainsGenericParameters) + { + builder.Append('<'); + for (int i = 0; i < GenericParameters.Count; i++) + { + if (i > 0) + builder.Append(", "); + builder.Append(GenericParameters[i].ToString(useFullNames)); + } + builder.Append('>'); + } + builder.Append(LLFinalStringParts()); + + return builder.ToString(); + } + + static string[] intNames = { + "Swift.Int", "Swift.UInt", "Swift.Int8", "Swift.UInt8", + "Swift.Int16", "Swift.UInt16", "Swift.Int32", "Swift.UInt32", + "Swift.Int64", "Swift.UInt64", "Swift.Char" + }; + + public static bool IsIntegral(TypeSpec ts) + { + NamedTypeSpec named = ts as NamedTypeSpec; + if (named == null) + return false; + return Array.IndexOf(intNames, named.Name) >= 0; + } + + public static bool IsFloatingPoint(TypeSpec ts) + { + NamedTypeSpec named = ts as NamedTypeSpec; + if (named == null) + return false; + return named.Name == "Swift.Float" || named.Name == "Swift.Double" || named.Name == "CoreGraphics.CGFloat"; + } + + public static bool IsBoolean(TypeSpec ts) + { + NamedTypeSpec named = ts as NamedTypeSpec; + if (named == null) + return false; + return named.Name == "Swift.Bool"; + } + + public static bool IsBuiltInValueType(TypeSpec ts) + { + return IsIntegral(ts) || IsFloatingPoint(ts) || IsBoolean(ts); + } + + public TypeSpec WithInOutSet() + { + var theSpec = TypeSpecParser.Parse(this.ToString()); + theSpec.IsInOut = true; + return theSpec; + } + + public bool IsDynamicSelf + { + get + { + return this is NamedTypeSpec ns && ns.Name == "Self"; + } + } + + public abstract bool HasDynamicSelf + { + get; + } + + public static bool AnyHasDynamicSelf(List types) + { + return types.Any(t => t.HasDynamicSelf); + } + + public TypeSpec ReplaceName(string toFind, string replacement) + { + var result = this; + if (!String.IsNullOrEmpty(replacement)) + ReplaceName(this, toFind, replacement, ref result); + return result; + } + + static bool ReplaceName(TypeSpec original, string toFind, string replacement, ref TypeSpec result) + { + result = original; + var changed = false; + switch (original.Kind) + { + case TypeSpecKind.Named: + changed = ReplaceName(original as NamedTypeSpec, toFind, replacement, ref result); + break; + case TypeSpecKind.ProtocolList: + changed = ReplaceName(original as ProtocolListTypeSpec, toFind, replacement, ref result); + break; + case TypeSpecKind.Closure: + changed = ReplaceName(original as ClosureTypeSpec, toFind, replacement, ref result); + break; + case TypeSpecKind.Tuple: + changed = ReplaceName(original as TupleTypeSpec, toFind, replacement, ref result); + break; + default: + throw new ArgumentOutOfRangeException($"Unknown TypeSpec kind {original.Kind}"); + } + if (changed) + { + result.Attributes.AddRange(original.Attributes); + result.TypeLabel = original.TypeLabel; + result.IsInOut = original.IsInOut; + result.IsAny = original.IsAny; + } + return changed; + } + + static bool ReplaceName(NamedTypeSpec named, string toFind, string replacement, ref TypeSpec result) + { + result = named; + var changed = false; + if (named.Name == toFind) + { + changed = true; + result = new NamedTypeSpec(replacement); + } + var resultGenerics = new List(named.GenericParameters.Count); + var changedGenerics = ReplaceName(named.GenericParameters, toFind, replacement, resultGenerics); + + if (changedGenerics) + { + if (!changed) + { + result = new NamedTypeSpec(named.Name); + } + result.GenericParameters.AddRange(resultGenerics); + } + else + { + if (changed) + result.GenericParameters.AddRange(named.GenericParameters); + } + return changed || changedGenerics; + } + + static bool ReplaceName(List originalTypes, string toFind, string replacement, List resultTypes) + { + var changed = false; + foreach (var type in originalTypes) + { + var result = type; + changed = ReplaceName(type, toFind, replacement, ref result) || changed; + resultTypes.Add(result); + } + return changed; + } + + static bool ReplaceName(TupleTypeSpec tuple, string toFind, string replacement, ref TypeSpec result) + { + List resultTypes = new List(tuple.Elements.Count); + if (ReplaceName(tuple.Elements, toFind, replacement, resultTypes)) + { + result = new TupleTypeSpec(resultTypes); + return true; + } + result = tuple; + return false; + } + + static bool ReplaceName(ProtocolListTypeSpec protolist, string toFind, string replacement, ref TypeSpec result) + { + var originalProtos = new List(protolist.Protocols.Count); + var resultProtos = new List(protolist.Protocols.Count); + originalProtos.AddRange(protolist.Protocols.Keys); + if (ReplaceName(originalProtos, toFind, replacement, resultProtos)) + { + result = new ProtocolListTypeSpec(resultProtos.OfType()); + return true; + } + return false; + } + + static bool ReplaceName(ClosureTypeSpec closure, string toFind, string replacement, ref TypeSpec result) + { + var resultArgs = closure.Arguments; + var resultReturn = closure.ReturnType; + + var argsChanged = ReplaceName(closure.Arguments, toFind, replacement, ref resultArgs); + var returnChanged = ReplaceName(closure.ReturnType, toFind, replacement, ref resultReturn); + if (argsChanged || returnChanged) + { + result = new ClosureTypeSpec(resultArgs, resultReturn); + return true; + } + return false; + } + } + + + public class NamedTypeSpec : TypeSpec + { + public NamedTypeSpec(string name) + : base(TypeSpecKind.Named) + { + // name = SwiftInterfaceReflector.SwiftInterfaceReflector.UnTick(name); + // Hack filter. + // For whatever reason, Any and AnyObject are not + // strictly in the Swift module. But they are. + // But they're not. + // What do I mean by this? + // Apple's demangler will print these as Swift.Any or + // Swift.AnyObject if the options are set to print + // fully qualified names, so I feel no remorse for doing + // this. + if (name == "Any") + name = "Swift.Any"; + else if (name == "AnyObject") + name = "Swift.AnyObject"; + Name = name; + } + + public NamedTypeSpec(string name, params TypeSpec[] genericSpecialization) + : this(name) + { + GenericParameters.AddRange(genericSpecialization); + } + + public NamedTypeSpec InnerType { get; set; } + + public bool IsProtocolList { get { return Name == "protocol"; } } + public string Name { get; private set; } + + protected override string LLToString(bool useFullName) + { + return useFullName ? Name : NameWithoutModule; + } + + protected override string LLFinalStringParts() + { + if (InnerType == null) + return ""; + return "." + InnerType; + } + + protected override bool LLEquals(TypeSpec other, bool partialNameMatch) + { + NamedTypeSpec spec = other as NamedTypeSpec; + if (spec == null) + return false; + var innersMatch = (InnerType == null && spec.InnerType == null) || (InnerType != null && InnerType.LLEquals(spec.InnerType, partialNameMatch)); + if (partialNameMatch) + { + return NameWithoutModule == spec.NameWithoutModule && innersMatch; + } + else + { + return Name == spec.Name && innersMatch; + } + } + + public bool HasModule(BaseDeclaration context, TypeMapper typeMapper) + { + if (Name.Contains(".")) + { + return !context.IsProtocolWithAssociatedTypesFullPath(new NamedTypeSpec(Name), typeMapper); + } + else + { + return false; + } + } + public string Module + { + get + { + return Name.Substring(0, Name.IndexOf('.')); + } + } + public string NameWithoutModule + { + get + { + return Name.IndexOf('.') >= 0 ? Name.Substring(Name.IndexOf('.') + 1) : Name; + } + } + + public override bool HasDynamicSelf + { + get + { + if (Name == "Self") + return true; + return TypeSpec.AnyHasDynamicSelf(GenericParameters); + } + } + } + + + public class TupleTypeSpec : TypeSpec + { + public TupleTypeSpec() + : base(TypeSpecKind.Tuple) + { + Elements = new List(); + } + + public TupleTypeSpec(TupleTypeSpec other) + : base(TypeSpecKind.Tuple) + { + Elements = new List(); + Elements.AddRange(other.Elements); + if (other.HasAttributes) + Attributes.AddRange(other.Attributes); + if (other.ContainsGenericParameters) + GenericParameters.AddRange(other.GenericParameters); + IsInOut = other.IsInOut; + } + + public TupleTypeSpec(IEnumerable elements) + : this() + { + Elements.AddRange(elements); + } + + public TupleTypeSpec(TypeSpec single) + : this() + { + Elements.Add(single); + } + + public List Elements { get; private set; } + + protected override string LLToString(bool useFullName) + { + StringBuilder builder = new StringBuilder(); + builder.Append('('); + for (int i = 0; i < Elements.Count; i++) + { + if (i > 0) + builder.Append(", "); + builder.Append(Elements[i].ToString(useFullName)); + } + builder.Append(')'); + return builder.ToString(); + } + + protected override bool LLEquals(TypeSpec other, bool partialNameMatch) + { + TupleTypeSpec spec = other as TupleTypeSpec; + if (spec == null) + return false; + return ListEqual(Elements, spec.Elements, partialNameMatch); + } + + public override bool IsEmptyTuple + { + get + { + return Elements.Count == 0; + } + } + + public override bool HasDynamicSelf => TypeSpec.AnyHasDynamicSelf(Elements); + + static TupleTypeSpec empty = new TupleTypeSpec(); + public static TupleTypeSpec Empty { get { return empty; } } + } + + public class ClosureTypeSpec : TypeSpec + { + public ClosureTypeSpec() + : base(TypeSpecKind.Closure) + { + } + + public ClosureTypeSpec(TypeSpec arguments, TypeSpec returnType) + : this() + { + Arguments = arguments; + ReturnType = returnType; + } + + static ClosureTypeSpec voidVoid = new ClosureTypeSpec(TupleTypeSpec.Empty, TupleTypeSpec.Empty); + + public static ClosureTypeSpec VoidVoid { get { return voidVoid; } } + + public TypeSpec Arguments { get; set; } + public TypeSpec ReturnType { get; set; } + public bool Throws { get; set; } + public bool IsAsync { get; set; } + + public bool HasReturn() + { + return ReturnType != null && !ReturnType.IsEmptyTuple; + } + + public bool HasArguments() + { + return Arguments != null && !Arguments.IsEmptyTuple; + } + + public TupleTypeSpec ArgumentsAsTuple + { + get + { + if (Arguments is TupleTypeSpec tuple) + return tuple; + return new TupleTypeSpec(Arguments); + } + } + + public int ArgumentCount() + { + if (!HasArguments()) + return 0; + if (Arguments is TupleTypeSpec tupe) + { + return tupe.Elements.Count; + } + return 1; + } + + public IEnumerable EachArgument() + { + if (!HasArguments()) + yield break; + TupleTypeSpec argList = Arguments as TupleTypeSpec; + if (argList != null) + { + foreach (TypeSpec arg in argList.Elements) + yield return arg; + } + else + { + yield return Arguments; + } + } + + public TypeSpec GetArgument(int index) + { + if (index < 0 || index >= ArgumentCount()) + throw new ArgumentOutOfRangeException(nameof(index)); + if (Arguments is TupleTypeSpec tuple) + return tuple.Elements[index]; + return Arguments; + } + + public bool IsEscaping + { + get + { + return HasAttributes && Attributes.Exists(attr => attr.Name == "escaping"); + } + } + + public bool IsAutoClosure + { + get + { + return HasAttributes && Attributes.Exists(attr => attr.Name == "autoclosure"); + } + } + + protected override string LLToString(bool useFullName) + { + StringBuilder builder = new StringBuilder(); + builder.Append(Arguments.ToString(useFullName)); + if (Throws) + builder.Append(" throws -> "); + else + builder.Append(" -> "); + builder.Append(ReturnType.ToString(useFullName)); + return builder.ToString(); + } + + protected override bool LLEquals(TypeSpec obj, bool partialNameMatch) + { + ClosureTypeSpec spec = obj as ClosureTypeSpec; + if (spec == null) + return false; + + if (partialNameMatch) + { + if (Arguments == null && spec.Arguments == null && + ReturnType == null && spec.ReturnType == null) + { + return true; + } + if (Arguments == null || spec.Arguments == null) + return false; + if (ReturnType == null || spec.ReturnType == null) + return false; + return Arguments.EqualsPartialMatch(spec.Arguments) && + ReturnType.EqualsPartialMatch(spec.ReturnType); + + } + else + { + var specArgs = spec.Arguments is TupleTypeSpec ? spec.Arguments : new TupleTypeSpec(spec.Arguments); + var thisArgs = Arguments is TupleTypeSpec ? Arguments : new TupleTypeSpec(Arguments); + return BothNullOrEqual(thisArgs, specArgs) && + BothNullOrEqual(ReturnType, spec.ReturnType); + } + } + + public override bool HasDynamicSelf + { + get + { + if (Arguments.HasDynamicSelf) + return true; + if (!IsNullOrEmptyTuple(ReturnType) && ReturnType.HasDynamicSelf) + return true; + return false; + } + } + } + + public class ProtocolListTypeSpec : TypeSpec + { + + class SpecComparer : IComparer + { + public int Compare(TypeSpec x, TypeSpec y) + { + if (x == null) + throw new ArgumentNullException(nameof(x)); + if (y == null) + throw new ArgumentNullException(nameof(y)); + + return StringComparer.Ordinal.Compare(x.ToString(), y.ToString()); + } + } + + class SpecEqComparer : IEqualityComparer + { + bool partialNameMatch; + public SpecEqComparer(bool partialNameMatch) + { + this.partialNameMatch = partialNameMatch; + } + + public bool Equals(TypeSpec x, TypeSpec y) + { + if (partialNameMatch) + return x.EqualsPartialMatch(y); + return x.Equals(y); + } + + public int GetHashCode(TypeSpec obj) + { + throw new NotImplementedException(); + } + } + + public ProtocolListTypeSpec() + : base(TypeSpecKind.ProtocolList) + { + Protocols = new SortedList(new SpecComparer()); + } + + public ProtocolListTypeSpec(IEnumerable protos) + : this() + { + foreach (var proto in protos) + Protocols.Add(proto, false); + } + + public SortedList Protocols { get; private set; } + + protected override bool LLEquals(TypeSpec other, bool partialNameMatch) + { + var otherProtos = other as ProtocolListTypeSpec; + if (otherProtos == null) + return false; + if (otherProtos.Protocols.Count != Protocols.Count) + return false; + var eqComparer = new SpecEqComparer(partialNameMatch); + + return Protocols.Keys.SequenceEqual(otherProtos.Protocols.Keys, eqComparer); + } + + protected override string LLToString(bool useFullName) + { + return Protocols.Keys.Select(proto => proto.ToString()).InterleaveStrings(" & "); + } + + public override bool HasDynamicSelf => false; + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecParser.cs b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecParser.cs new file mode 100644 index 000000000000..c82a4bb0c57b --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecParser.cs @@ -0,0 +1,344 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Collections.Generic; +using SwiftReflector.ExceptionTools; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class TypeSpecParser + { + TextReader reader; + TypeSpecTokenizer tokenizer; + + TypeSpecParser(TextReader reader) + { + this.reader = reader; + tokenizer = new TypeSpecTokenizer(reader); + } + + TypeSpec Parse() + { + TypeSpecToken token = tokenizer.Peek(); + TypeSpec type = null; + List attrs = null; + var inout = false; + var isAny = false; + string typeLabel = null; + var throwsClosure = false; + var asyncClosure = false; + var expectClosure = false; + + // Prefix + + // parse any attributes + if (token.Kind == TypeTokenKind.At) + { + attrs = ParseAttributes(); + token = tokenizer.Peek(); + } + + // looks like it's inout + if (token.Kind == TypeTokenKind.TypeName && token.Value == "inout") + { + inout = true; + tokenizer.Next(); + token = tokenizer.Peek(); + } + + if (token.Kind == TypeTokenKind.TypeName && token.Value == "any") + { + isAny = true; + tokenizer.Next(); + token = tokenizer.Peek(); + } + + if (token.Kind == TypeTokenKind.TypeLabel) + { + typeLabel = token.Value; + tokenizer.Next(); + token = tokenizer.Peek(); + } + + + // meat + + + if (token.Kind == TypeTokenKind.LeftParenthesis) + { // tuple + tokenizer.Next(); + TupleTypeSpec tuple = ParseTuple(); + type = tuple.Elements.Count == 1 ? tuple.Elements[0] : tuple; + typeLabel = type.TypeLabel; + type.TypeLabel = null; + } + else if (token.Kind == TypeTokenKind.TypeName) + { // name + tokenizer.Next(); + var tokenValue = token.Value.StartsWith("ObjectiveC.", StringComparison.Ordinal) ? + "Foundation" + token.Value.Substring("ObjectiveC".Length) : token.Value; + if (tokenValue == "Swift.Void") + type = TupleTypeSpec.Empty; + else + type = new NamedTypeSpec(tokenValue); + } + else if (token.Kind == TypeTokenKind.LeftBracket) + { // array + tokenizer.Next(); + type = ParseArray(); + } + else + { // illegal + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 0, $"Unexpected token {token.Value}."); + } + + if (tokenizer.NextIs("async")) + { + tokenizer.Next(); + asyncClosure = true; + expectClosure = true; + } + + if (tokenizer.NextIs("throws")) + { + tokenizer.Next(); + throwsClosure = true; + expectClosure = true; + } + + if (tokenizer.Peek().Kind == TypeTokenKind.Arrow) + { + tokenizer.Next(); + type = ParseClosure(type, throwsClosure, asyncClosure); + expectClosure = false; + throwsClosure = false; + asyncClosure = false; + } + else if (expectClosure) + { + var errorCase = asyncClosure && throwsClosure ? "'async throws'" : asyncClosure ? "'async'" : "'throws'"; + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 1, $"Unexpected token {tokenizer.Peek().Value} after {errorCase} in a closure."); + } + else if (tokenizer.Peek().Kind == TypeTokenKind.LeftAngle) + { + tokenizer.Next(); + type = Genericize(type); + } + + if (tokenizer.Peek().Kind == TypeTokenKind.Period) + { + tokenizer.Next(); + var currType = type as NamedTypeSpec; + if (currType == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 2, $"In parsing an inner type (type.type), first element is a {type.Kind} instead of a NamedTypeSpec."); + var nextType = Parse() as NamedTypeSpec; + if (nextType == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 3, $"In parsing an inner type (type.type), the second element is a {nextType.Kind} instead of a NamedTypeSpec"); + currType.InnerType = nextType; + } + + // Postfix + + if (tokenizer.Peek().Kind == TypeTokenKind.Ampersand) + { + type = ParseProtocolList(type as NamedTypeSpec); + } + + while (tokenizer.Peek().Kind == TypeTokenKind.QuestionMark) + { + tokenizer.Next(); + type = WrapAsBoundGeneric(type, "Swift.Optional"); + } + + if (tokenizer.Peek().Kind == TypeTokenKind.ExclamationPoint) + { + tokenizer.Next(); + type = WrapAsBoundGeneric(type, "Swift.ImplicitlyUnwrappedOptional"); + } + + type.IsInOut = inout; + type.IsAny = isAny; + type.TypeLabel = typeLabel; + + if (type != null && attrs != null) + { + type.Attributes.AddRange(attrs); + } + + return type; + } + + List ParseAttributes() + { + // An attribute is + // @name + // or + // @name [ parameters ] + // The spec says that it could be ( parameters ), [ parameters ], or { parameters } + // but the reflection code should make certain that it's [ parameters ]. + List attrs = new List(); + while (true) + { + if (tokenizer.Peek().Kind != TypeTokenKind.At) + { + return attrs; + } + tokenizer.Next(); + if (tokenizer.Peek().Kind != TypeTokenKind.TypeName) + { + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 5, $"Unexpected token {tokenizer.Peek().Value}, expected a name while parsing an attribute."); + } + string name = tokenizer.Next().Value; + TypeSpecAttribute attr = new TypeSpecAttribute(name); + if (tokenizer.Peek().Kind == TypeTokenKind.LeftBracket) + { + tokenizer.Next(); + ParseAttributeParameters(attr.Parameters); + } + attrs.Add(attr); + } + } + + void ParseAttributeParameters(List parameters) + { + // Attribute parameters are funny + // The contents between the brackets vary. + // They may be comma separated. They may not. + // Therefore this code is likely to break, but since I'm responsible for + // generating the text of the attributes parsed here, I can try to ensure + // that it will always fit the pattern. + while (true) + { + if (tokenizer.Peek().Kind == TypeTokenKind.RightBracket) + { + tokenizer.Next(); + return; + } + TypeSpecToken value = tokenizer.Next(); + if (value.Kind != TypeTokenKind.TypeName) + { + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 6, $"Unexpected token {value.Value} while parsing attribute parameter."); + } + parameters.Add(value.Value); + if (tokenizer.Peek().Kind == TypeTokenKind.Comma) + { + tokenizer.Next(); + } + } + } + + TypeSpec ParseProtocolList(NamedTypeSpec first) + { + ArgumentNullException.ThrowIfNull(first, nameof(first)); + var protocols = new List(); + protocols.Add(first); + while (true) + { + if (tokenizer.Peek().Kind != TypeTokenKind.Ampersand) + break; + tokenizer.Next(); + var nextName = tokenizer.Next(); + if (nextName.Kind != TypeTokenKind.TypeName) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 13, $"Unexpected token '{nextName.Value}' with kind {nextName.Kind} while parsing a protocol list"); + protocols.Add(new NamedTypeSpec(nextName.Value)); + } + return new ProtocolListTypeSpec(protocols); + } + + void ConsumeList(List elements, TypeTokenKind terminator, string typeImParsing) + { + while (true) + { + if (tokenizer.Peek().Kind == terminator) + { + tokenizer.Next(); + return; + } + TypeSpec next = Parse(); + if (next == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 8, $"Unexpected end while parsing a {typeImParsing}"); + elements.Add(next); + if (tokenizer.Peek().Kind == TypeTokenKind.Comma) + { + tokenizer.Next(); + } + } + } + + TypeSpec Genericize(TypeSpec type) + { + ConsumeList(type.GenericParameters, TypeTokenKind.RightAngle, "generic parameter list"); + return type; + } + + TypeSpec WrapAsBoundGeneric(TypeSpec type, string name) + { + var result = new NamedTypeSpec(name); + result.GenericParameters.Add(type); + return result; + } + + TupleTypeSpec ParseTuple() + { + TupleTypeSpec tuple = new TupleTypeSpec(); + ConsumeList(tuple.Elements, TypeTokenKind.RightParenthesis, "tuple"); + return tuple; + } + + NamedTypeSpec ParseArray() + { + var keyType = Parse(); + TypeSpec valueType = null; + if (keyType == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 9, "Unexpected end while parsing an array or dictionary."); + if (tokenizer.Peek().Kind == TypeTokenKind.Colon) + { + tokenizer.Next(); + valueType = Parse(); + if (valueType == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 10, "Unexpected end while parsing a dictionary value type."); + } + else if (tokenizer.Peek().Kind != TypeTokenKind.RightBracket) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 11, "Expected a right bracket after an array or dictionary."); + + tokenizer.Next(); + + if (valueType == null) + { + var array = new NamedTypeSpec("Swift.Array"); + array.GenericParameters.Add(keyType); + return array; + } + else + { + var dictionary = new NamedTypeSpec("Swift.Dictionary"); + dictionary.GenericParameters.Add(keyType); + dictionary.GenericParameters.Add(valueType); + return dictionary; + } + } + + ClosureTypeSpec ParseClosure(TypeSpec arg, bool throws, bool isAsync) + { + TypeSpec returnType = Parse(); + if (returnType == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 12, "Unexpected end while parsing a closure."); + ClosureTypeSpec closure = new ClosureTypeSpec(); + closure.Arguments = arg; + closure.ReturnType = returnType; + closure.Throws = throws; + closure.IsAsync = isAsync; + return closure; + } + + public static TypeSpec Parse(string typeName) + { + TypeSpecParser parser = new TypeSpecParser(new StringReader(typeName)); + return parser.Parse(); + } + } +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecToken.cs b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecToken.cs new file mode 100644 index 000000000000..70bc6b54d203 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecToken.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using SwiftRuntimeLibrary; + +namespace SwiftReflector.SwiftXmlReflection +{ + public class TypeSpecToken + { + TypeSpecToken(TypeTokenKind kind, string value) + { + Kind = kind; + Value = value; + } + public TypeTokenKind Kind { get; private set; } + public string Value { get; private set; } + public static TypeSpecToken LabelFromString(string value) + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + return new TypeSpecToken(TypeTokenKind.TypeLabel, value); + } + public static TypeSpecToken FromString(string value) + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + return new TypeSpecToken(TypeTokenKind.TypeName, value); + } + static TypeSpecToken leftparenthesis = new TypeSpecToken(TypeTokenKind.LeftParenthesis, "("); + static TypeSpecToken rightparenthesis = new TypeSpecToken(TypeTokenKind.RightParenthesis, ")"); + static TypeSpecToken leftangle = new TypeSpecToken(TypeTokenKind.LeftAngle, "<"); + static TypeSpecToken rightangle = new TypeSpecToken(TypeTokenKind.RightAngle, ">"); + static TypeSpecToken comma = new TypeSpecToken(TypeTokenKind.Comma, ","); + static TypeSpecToken arrow = new TypeSpecToken(TypeTokenKind.Arrow, "->"); + static TypeSpecToken at = new TypeSpecToken(TypeTokenKind.At, "@"); + static TypeSpecToken questionmark = new TypeSpecToken(TypeTokenKind.QuestionMark, "?"); + static TypeSpecToken exclamationpoint = new TypeSpecToken(TypeTokenKind.ExclamationPoint, "!"); + static TypeSpecToken done = new TypeSpecToken(TypeTokenKind.Done, ""); + static TypeSpecToken leftbracket = new TypeSpecToken(TypeTokenKind.LeftBracket, "["); + static TypeSpecToken rightbracket = new TypeSpecToken(TypeTokenKind.RightBracket, "]"); + static TypeSpecToken colon = new TypeSpecToken(TypeTokenKind.Colon, ":"); + static TypeSpecToken period = new TypeSpecToken(TypeTokenKind.Period, ".'"); + static TypeSpecToken ampersand = new TypeSpecToken(TypeTokenKind.Ampersand, "&"); + + public static TypeSpecToken LeftParenthesis { get { return leftparenthesis; } } + public static TypeSpecToken RightParenthesis { get { return rightparenthesis; } } + public static TypeSpecToken LeftAngle { get { return leftangle; } } + public static TypeSpecToken RightAngle { get { return rightangle; } } + public static TypeSpecToken Comma { get { return comma; } } + public static TypeSpecToken Arrow { get { return arrow; } } + public static TypeSpecToken At { get { return at; } } + public static TypeSpecToken QuestionMark { get { return questionmark; } } + public static TypeSpecToken ExclamationPoint { get { return exclamationpoint; } } + public static TypeSpecToken Done { get { return done; } } + public static TypeSpecToken LeftBracket { get { return leftbracket; } } + public static TypeSpecToken RightBracket { get { return rightbracket; } } + public static TypeSpecToken Colon { get { return colon; } } + public static TypeSpecToken Period { get { return period; } } + public static TypeSpecToken Ampersand { get { return ampersand; } } + public override string ToString() + { + return Value; + } + } + +} + diff --git a/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecTokenizer.cs b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecTokenizer.cs new file mode 100644 index 000000000000..c7218d134de8 --- /dev/null +++ b/src/SwiftReflector/src/SwiftXmlReflection/TypeSpecTokenizer.cs @@ -0,0 +1,225 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Text; +using System.IO; +using SwiftReflector.ExceptionTools; + +namespace SwiftReflector.SwiftXmlReflection +{ + + public class TypeSpecTokenizer + { + enum State + { + Start, + InName, + InArrow, + }; + + State state; + StringBuilder buffer; + TextReader reader; + static string invalidNameChars; + + static TypeSpecTokenizer() + { + // OK - thanks Apple. Since identifiers in Swift can be any messed up unicode, including emoji, we + // can't just ask "IsLetterOrNumber". Instead, I build the set of characters that are specifically + // forbidden. Guh. + StringBuilder sb = new StringBuilder(); + for (char c = (char)0; c < '.'; c++) + { + sb.Append(c); + } + sb.Append('/'); + for (char c = ':'; c < 'A'; c++) + { + sb.Append(c); + } + for (char c = '['; c < '_'; c++) + { + sb.Append(c); + } + sb.Append('`'); + for (char c = '{'; c <= (char)127; c++) + { + sb.Append(c); + } + invalidNameChars = sb.ToString(); + } + + public TypeSpecTokenizer(TextReader reader) + { + this.reader = reader; + buffer = new StringBuilder(); + state = State.Start; + } + + TypeSpecToken curr = null; + + public TypeSpecToken Peek() + { + if (curr == null) + { + curr = Next(); + } + return curr; + } + + public TypeSpecToken Next() + { + if (curr != null) + { + TypeSpecToken retval = curr; + curr = null; + return retval; + } + TypeSpecToken token = null; + do + { + switch (state) + { + case State.InName: + token = DoName(); + break; + case State.InArrow: + token = DoArrow(); + break; + case State.Start: + token = DoStart(); + break; + } + } while (token == null); + return token; + } + + public bool NextIs(string name) + { + return Peek().Kind == TypeTokenKind.TypeName && Peek().Value == name; + } + + TypeSpecToken DoName() + { + int curr = reader.Peek(); + if (curr < 0 || InvalidNameCharacter((char)curr)) + { + if (curr == ':') + { + reader.Read(); // drop the colon + state = State.Start; + TypeSpecToken token = TypeSpecToken.LabelFromString(buffer.ToString()); + buffer.Clear(); + return token; + } + else + { + state = State.Start; + TypeSpecToken token = TypeSpecToken.FromString(buffer.ToString()); + buffer.Clear(); + return token; + } + } + else + { + buffer.Append((char)reader.Read()); + return null; + } + } + + TypeSpecToken DoArrow() + { + if (buffer.Length == 0) + { + if (reader.Peek() == (int)'-') + { + buffer.Append((char)reader.Read()); + return null; + } + } + else + { + if (reader.Peek() == (int)'>') + { + reader.Read(); + buffer.Clear(); + state = State.Start; + return TypeSpecToken.Arrow; + } + } + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 4, $"Unexpected character {(char)reader.Peek()} while parsing '->'."); + } + + TypeSpecToken DoStart() + { + int currentChar = reader.Peek(); + if (currentChar < 0) + return TypeSpecToken.Done; + char c = (char)currentChar; + switch (c) + { + case '(': + reader.Read(); + return TypeSpecToken.LeftParenthesis; + case ')': + reader.Read(); + return TypeSpecToken.RightParenthesis; + case '<': + reader.Read(); + return TypeSpecToken.LeftAngle; + case '>': + reader.Read(); + return TypeSpecToken.RightAngle; + case ',': + reader.Read(); + return TypeSpecToken.Comma; + case '@': + reader.Read(); + return TypeSpecToken.At; + case '?': + reader.Read(); + return TypeSpecToken.QuestionMark; + case '!': + reader.Read(); + return TypeSpecToken.ExclamationPoint; + case '-': + state = State.InArrow; + return null; + case '[': + reader.Read(); + return TypeSpecToken.LeftBracket; + case ']': + reader.Read(); + return TypeSpecToken.RightBracket; + case ':': + reader.Read(); + return TypeSpecToken.Colon; + case '.': + reader.Read(); + return TypeSpecToken.Period; + case '&': + reader.Read(); + return TypeSpecToken.Ampersand; + default: + if (Char.IsWhiteSpace(c)) + { + reader.Read(); + return null; + } + if (InvalidNameCharacter(c)) + { + throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 7, $"Unexpected/illegal char {c}"); + } + state = State.InName; + return null; + } + } + + static bool InvalidNameCharacter(char c) + { + return invalidNameChars.IndexOf(c) >= 0; + } + } +} + diff --git a/src/SwiftReflector/src/TypeMapping/Entity.cs b/src/SwiftReflector/src/TypeMapping/Entity.cs new file mode 100644 index 000000000000..cb8d7a0c5560 --- /dev/null +++ b/src/SwiftReflector/src/TypeMapping/Entity.cs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SwiftReflector.SwiftXmlReflection; +using System.Xml.Linq; + +namespace SwiftReflector.TypeMapping +{ + public class Entity : IXElementConvertible + { + public Entity() + { + } + + public string SharpNamespace { get; set; } + public string SharpTypeName { get; set; } + public EntityType EntityType { get; set; } + public string ProtocolProxyModule { get; set; } + public bool IsDiscretionaryConstraint { get; set; } + + public TypeDeclaration Type { get; set; } + + public DotNetName GetFullType() + { + return new DotNetName(SharpNamespace, SharpTypeName); + } + + public bool IsStructOrEnum + { + get + { + return EntityType == EntityType.Struct || EntityType == EntityType.Enum || + EntityType == EntityType.TrivialEnum; + } + } + + public bool IsStructClassOrEnum + { + get + { + return IsStructOrEnum || EntityType == EntityType.Class; + } + } + + public bool IsObjCClass + { + get + { + return EntityType == EntityType.Class && (Type != null && Type.IsObjC); + } + } + + public bool IsObjCStruct + { + get + { + return EntityType == EntityType.Struct && (Type != null && Type.IsObjC); + } + } + + public bool IsObjCEnum + { + get + { + return EntityType == EntityType.Enum && (Type != null && Type.IsObjC); + } + } + + public bool IsObjCProtocol + { + get + { + return EntityType == EntityType.Protocol && (Type != null && Type.IsObjC); + } + } + + #region IXElementConvertible implementation + + public XElement ToXElement() + { + return new XElement("entity", + new XAttribute("sharpNameSpace", SharpNamespace), + new XAttribute("sharpTypeName", SharpTypeName), + new XAttribute("entityType", EntityType), + new XAttribute("protocolProxyModule", ProtocolProxyModule ?? ""), + new XAttribute("discretionaryConstraint", IsDiscretionaryConstraint ? "true" : "false"), + Type.ToXElement()); + } + + #endregion + } +} + diff --git a/src/SwiftReflector/src/TypeMapping/ModuleDatabase.cs b/src/SwiftReflector/src/TypeMapping/ModuleDatabase.cs new file mode 100644 index 000000000000..4f3f54c68aad --- /dev/null +++ b/src/SwiftReflector/src/TypeMapping/ModuleDatabase.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using SwiftReflector.SwiftXmlReflection; + +namespace SwiftReflector.TypeMapping +{ + public class ModuleDatabase : Dictionary + { + public ModuleDatabase() + { + Operators = new List(); + TypeAliases = new List(); + } + + public List Operators { get; private set; } + public List TypeAliases { get; private set; } + } +} diff --git a/src/SwiftReflector/src/TypeMapping/NetParam.cs b/src/SwiftReflector/src/TypeMapping/NetParam.cs new file mode 100644 index 000000000000..1bc6a961e843 --- /dev/null +++ b/src/SwiftReflector/src/TypeMapping/NetParam.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using SwiftRuntimeLibrary; + +namespace SwiftReflector.TypeMapping +{ + public class NetParam + { + public NetParam(string name, NetTypeBundle bundle) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Name = name; + Type = bundle; + } + public string Name { get; private set; } + public NetTypeBundle Type { get; private set; } + } + +} + diff --git a/src/SwiftReflector/src/TypeMapping/NetTypeBundle.cs b/src/SwiftReflector/src/TypeMapping/NetTypeBundle.cs new file mode 100644 index 000000000000..3032f7acd1d8 --- /dev/null +++ b/src/SwiftReflector/src/TypeMapping/NetTypeBundle.cs @@ -0,0 +1,238 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using SyntaxDynamo.CSLang; +using SwiftReflector.SwiftXmlReflection; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.TypeMapping +{ + public class NetTypeBundle + { + const string kNoType = "!!NO_TYPE!!"; + List genericTypes = new List(); + + public NetTypeBundle(string nameSpace, string entityName, bool isScalar, bool isReference, EntityType entity, + bool swiftThrows = false) + { + GenericIndex = -1; + IsVoid = entityName == kNoType; + Type = entityName; + NameSpace = nameSpace; + + FullName = String.IsNullOrEmpty(nameSpace) ? entityName : nameSpace + "." + entityName; + IsScalar = isScalar; + IsReference = isReference; + Entity = entity; + Throws = swiftThrows; + } + + public NetTypeBundle(List tupleElements, bool isReference) + { + GenericIndex = -1; + string netTypeName = ToTupleName(tupleElements); + FullName = "System." + netTypeName; + Type = netTypeName; + NameSpace = "System"; + + IsScalar = false; + IsReference = isReference; + Entity = EntityType.Tuple; + ArgumentNullException.ThrowIfNull(tupleElements, nameof(tupleElements)); + TupleTypes.AddRange(tupleElements); + } + + public NetTypeBundle(string nameSpace, string entityName, EntityType entity, bool isReference, IEnumerable genericTypes, + bool swiftThrows = false) + : this(nameSpace, entityName, false, isReference, entity) + { + GenericIndex = -1; + this.genericTypes.AddRange(genericTypes); + if (this.genericTypes.Count == 0) + throw new ArgumentOutOfRangeException(nameof(genericTypes), "Generic NetBundle constructor needs actual generic types."); + Throws = swiftThrows; + } + + public NetTypeBundle(int depth, int index) + { + if (depth < 0) + throw new ArgumentOutOfRangeException(nameof(depth)); + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index)); + GenericDepth = depth; + GenericIndex = index; + } + + public NetTypeBundle(ProtocolDeclaration proto, AssociatedTypeDeclaration assoc, bool isReference) + { + GenericIndex = -1; + AssociatedTypeProtocol = proto; + AssociatedType = assoc; + // Type = OverrideBuilder.GenericAssociatedTypeName (assoc); + FullName = Type; + NameSpace = String.Empty; + IsReference = isReference; + } + + public NetTypeBundle(string selfRepresentation, bool isReference) + { + ArgumentNullException.ThrowIfNull(selfRepresentation, nameof(selfRepresentation)); + GenericIndex = -1; + Type = FullName = selfRepresentation; + NameSpace = String.Empty; + IsReference = isReference; + IsSelf = true; + } + + static NetTypeBundle ntbVoid = new NetTypeBundle("", kNoType, false, false, EntityType.None); + + public static NetTypeBundle Void { get { return ntbVoid; } } + + static NetTypeBundle ntbIntPtr = new NetTypeBundle("System", "IntPtr", false, false, EntityType.None); + public static NetTypeBundle IntPtr + { + get + { + return ntbIntPtr; + } + } + + public bool IsSelf { get; private set; } + public bool IsVoid { get; private set; } + public string Type { get; private set; } + public string NameSpace { get; private set; } + public string FullName { get; private set; } + public bool IsScalar { get; private set; } + public bool IsReference { get; private set; } + public EntityType Entity { get; private set; } + public List TupleTypes { get { return genericTypes; } } + public NetTypeBundle OptionalType { get { return genericTypes[0]; } } + public List GenericTypes { get { return genericTypes; } } + public int GenericDepth { get; private set; } + public int GenericIndex { get; private set; } + public bool IsGenericReference { get { return GenericIndex >= 0; } } + public ProtocolDeclaration AssociatedTypeProtocol { get; private set; } + public AssociatedTypeDeclaration AssociatedType { get; private set; } + public bool IsAssociatedType { get { return AssociatedTypeProtocol != null; } } + public bool Throws { get; private set; } + public bool ContainsGenericParts + { + get + { + return genericTypes.Count > 0; + } + } + public List GenericConstraints + { + get + { + return IsGenericReference ? GenericTypes : null; + } + } + + public override string ToString() + { + return FullName; + } + + public override bool Equals(object obj) + { + NetTypeBundle other = obj as NetTypeBundle; + if (other == null) + return false; + return FullName == other.FullName; + } + + public override int GetHashCode() + { + return FullName.GetHashCode(); + } + + static string ToTupleName(IEnumerable types) + { + StringBuilder sb = new StringBuilder(); + bool first = true; + sb.Append("Tuple<"); + foreach (NetTypeBundle t in types) + { + if (!first) + { + sb.Append(", "); + } + first = false; + sb.Append(t.FullName); + } + return sb.Append(">").ToString(); + } + + static string ToOptionalName(NetTypeBundle optType) + { + StringBuilder sb = new StringBuilder(); + sb.Append("SwiftOptional<").Append(optType.FullName).Append(">"); + return sb.ToString(); + } + + + static IEnumerable ToCSSimpleType(IEnumerable ntbs, CSUsingPackages use) + { + return ntbs.Select(ntb => ToCSSimpleType(ntb, use)); + } + + public static CSType ToCSSimpleType(NetTypeBundle ntb, CSUsingPackages use) + { + if (!String.IsNullOrEmpty(ntb.NameSpace)) + use.AddIfNotPresent(ntb.NameSpace); + return ntb.Entity == EntityType.Tuple ? ToCSTuple(ntb.TupleTypes, use) : ntb.ToCSType(use); + } + + public static CSSimpleType ToCSOptional(NetTypeBundle optType, CSUsingPackages use) + { + // use.AddIfNotPresent (typeof (SwiftOptional<>)); + // return new CSSimpleType ("SwiftOptional", false, optType.ToCSType (use)); + throw new Exception(); + } + + public static CSSimpleType ToCSTuple(IList innerTypes, CSUsingPackages use) + { + if (innerTypes.Count <= 7) + { + return new CSSimpleType("Tuple", false, ToCSSimpleType(innerTypes, use).ToArray()); + } + else + { + IEnumerable head = ToCSSimpleType(innerTypes.Take(7), use); + CSType tail = ToCSTuple(innerTypes.Skip(7).ToList(), use); + return new CSSimpleType("Tuple", false, Enumerable.Concat(head, Enumerable.Repeat(tail, 1)).ToArray()); + } + } + + public CSType ToCSType(CSUsingPackages use) + { + if (!String.IsNullOrEmpty(NameSpace)) + use.AddIfNotPresent(NameSpace); + if (IsGenericReference) + { + CSGenericReferenceType genref = new CSGenericReferenceType(GenericDepth, GenericIndex); + if (this.GenericConstraints.Count > 0) + { + genref.InterfaceConstraints.AddRange(this.GenericConstraints.Select(ntb => ntb.ToCSType(use))); + } + return genref; + } + else if (IsAssociatedType || IsSelf) + { + return new CSSimpleType(Type, false); + } + + return Entity == EntityType.Tuple ? ToCSTuple(TupleTypes, use) : + new CSSimpleType(Type, false, GenericTypes.Select(ntb => ntb.ToCSType(use)).ToArray()); + } + + + } +} + diff --git a/src/SwiftReflector/src/TypeMapping/TypeDatabase.cs b/src/SwiftReflector/src/TypeMapping/TypeDatabase.cs new file mode 100644 index 000000000000..694a1d49e3bb --- /dev/null +++ b/src/SwiftReflector/src/TypeMapping/TypeDatabase.cs @@ -0,0 +1,412 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Xml.Linq; +using SwiftReflector.SwiftXmlReflection; +using SwiftReflector.ExceptionTools; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.TypeMapping +{ + public class DotNetName + { + public readonly string Namespace; + public readonly string TypeName; + + public DotNetName(string @namespace, string typeName) + { + Namespace = @namespace; + TypeName = typeName; + } + + public override string ToString() + { + return $"{Namespace}.{TypeName}"; + } + + public override bool Equals(object obj) + { + var other = obj as DotNetName; + return other != null && Namespace == other.Namespace && TypeName == other.TypeName; + } + + public override int GetHashCode() + { + return Namespace.GetHashCode() ^ TypeName.GetHashCode(); + } + } + + public class TypeDatabase + { + const double kCurrentVersion = 1.0; + const double kMinVersion = 1.0; + Dictionary netNamesToSwiftNames = new Dictionary(); + Dictionary swiftNamesToNetNames = new Dictionary(); + + Dictionary modules = new Dictionary(); + public IEnumerable ModuleNames { get { return modules.Keys; } } + + public int Count + { + get + { + return modules.Select(m => m.Value.Count).Sum(); + } + } + + public TypeDatabase() + { + } + + public DotNetName DotNetNameForSwiftName(string swiftName) + { + DotNetName netName = null; + ArgumentNullException.ThrowIfNull(swiftName, nameof(swiftName)); + swiftNamesToNetNames.TryGetValue(swiftName, out netName); + return netName; // may be null + } + + public DotNetName DotNetNameForSwiftName(SwiftClassName swiftName) + { + ArgumentNullException.ThrowIfNull(swiftName, nameof(swiftName)); + return DotNetNameForSwiftName(swiftName.ToFullyQualifiedName(true)); + } + + public string SwiftNameForDotNetName(DotNetName netName) + { + string swiftName = null; + ArgumentNullException.ThrowIfNull(netName, nameof(netName)); + netNamesToSwiftNames.TryGetValue(netName, out swiftName); + return swiftName; + } + + public Entity EntityForDotNetName(DotNetName netClassName) + { + return EntityForSwiftName(netNamesToSwiftNames[netClassName]); + } + + public Entity EntityForSwiftName(SwiftClassName swiftName) + { + return EntityForSwiftName(swiftName.ToFullyQualifiedName(true)); + } + + public Entity EntityForSwiftName(string swiftName) + { + var modName = swiftName.ModuleFromName(); + if (modName == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 1, $"Swift name '{swiftName}' needs to have a module."); + + var module = EntityCollection(modName); + if (module == null) + return null; + + Entity e = null; + module.TryGetValue(swiftName, out e); + return e; + } + + public Entity TryGetEntityForSwiftName(string swiftName) + { + try + { + return EntityForSwiftName(swiftName); + } + catch + { + return null; + } + } + + public void Add(Entity e) + { + if (e.Type != null && !e.Type.IsUnrooted) + throw new ArgumentException("Entity.Type needs to be unrooted.", "e"); + var errors = new ErrorHandling(); + AddEntity(e, errors); + if (errors.AnyErrors) + throw new AggregateException(errors.Errors.Select((v) => v.Exception)); + } + + ModuleDatabase EntityCollection(string moduleName) + { + ModuleDatabase module = null; + ArgumentNullException.ThrowIfNull(moduleName, nameof(moduleName)); + modules.TryGetValue(moduleName, out module); + return module; + } + + public IEnumerable EntitiesForModule(string moduleName) + { + var module = EntityCollection(moduleName); + if (module != null) + return module.Values; + return Enumerable.Empty(); + } + + public IEnumerable OperatorsForModule(string moduleName) + { + var module = EntityCollection(moduleName); + if (module != null) + return module.Operators; + return Enumerable.Empty(); + } + + public IEnumerable TypeAliasesForModule(string moduleName) + { + var module = EntityCollection(moduleName); + if (module != null) + return module.TypeAliases; + return Enumerable.Empty(); + } + + public ErrorHandling Read(List files) + { + var errors = new ErrorHandling(); + foreach (string file in files) + { + errors.Add(Read(file)); + } + return errors; + } + + public ErrorHandling Read(string file) + { + var errors = new ErrorHandling(); + Stream stm = null; + try + { + stm = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read); + errors.Add(Read(stm)); + } + catch (Exception e) + { + errors.Add(ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 59, e, "Failed opening file {0}: {1}", file, e.Message)); + } + finally + { + if (stm != null) + stm.Close(); + } + return errors; + } + + public ErrorHandling Read(Stream stm) + { + var errors = new ErrorHandling(); + try + { + var doc = XDocument.Load(stm); + var xamtypedatabase = doc.Element("xamtypedatabase"); + if (xamtypedatabase == null) + throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 2, "Type database is missing required key 'xamtypedatabase'"); + var version = xamtypedatabase.DoubleAttribute("version", -1.0); + if (version < kMinVersion) + if (version > kCurrentVersion) + throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 3, $"Type database version, {version}, is greater than the current version, {kCurrentVersion}."); + ReadVersion1_0(xamtypedatabase, errors); + } + catch (Exception e) + { + errors.Add(ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 60, e, "Failure reading type definition XML: " + e.Message)); + } + return errors; + } + + void ReadVersion1_0(XElement typeDbRoot, ErrorHandling errors) + { + var localModules = new Dictionary(); + + var entityLists = typeDbRoot.Descendants("entities"); + + foreach (var entityList in entityLists) + { + var entities = from entity in entityList.Elements("entity") + select EntityFromXElement(entity, localModules, errors); + + foreach (Entity e in entities) + { + if (e == null) + continue; + AddEntity(e, errors); + } + + var ops = from op in entityList.Elements("operator") + select OperatorDeclaration.FromXElement(op, null); + + foreach (var op in ops) + { + AddOperator(op); + } + + var aliases = from alias in entityList.Elements("typealias") + select TypeAliasDeclaration.FromXElement(null, alias); + + foreach (var alias in aliases) + { + AddTypeAlias(alias); + } + } + } + + public ModuleDatabase ModuleDatabaseForModuleName(string moduleName) + { + ModuleDatabase db; + if (!modules.TryGetValue(moduleName, out db)) + { + db = new ModuleDatabase(); + modules.Add(moduleName, db); + } + return db; + } + + public void AddOperator(OperatorDeclaration op, string moduleName = null) + { + moduleName = moduleName ?? op.ModuleName; + ModuleDatabase db = ModuleDatabaseForModuleName(moduleName); + db.Operators.Add(op); + } + + public IEnumerable FindOperators(IEnumerable moduleNames) + { + foreach (var moduleName in moduleNames) + { + ModuleDatabase db = null; + if (!modules.TryGetValue(moduleName, out db)) + continue; + foreach (var op in db.Operators) + yield return op; + } + yield break; + } + + public void AddTypeAlias(TypeAliasDeclaration alias, string moduleName = null) + { + moduleName = moduleName ?? alias.ModuleName; + ModuleDatabase db = ModuleDatabaseForModuleName(moduleName); + db.TypeAliases.Add(alias); + } + + void AddEntity(Entity e, ErrorHandling errors) + { + var swiftName = e.Type.ToFullyQualifiedName(true); + var sharpName = e.GetFullType(); + if (netNamesToSwiftNames.ContainsKey(sharpName)) + { + errors.Add(new ReflectorError(ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 4, $"Already have a C# definition for {e.EntityType} {sharpName}"))); + return; + } + if (swiftNamesToNetNames.ContainsKey(swiftName)) + { + errors.Add(new ReflectorError(ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 5, $"Already have a Swift definition for {e.EntityType} {swiftName}"))); + return; + } + + netNamesToSwiftNames.Add(sharpName, swiftName); + swiftNamesToNetNames.Add(swiftName, sharpName); + + var moduleName = e.Type.Module.Name; + AddEntityToModuleCollection(moduleName, e); + } + + void AddEntityToModuleCollection(string moduleName, Entity e) + { + ModuleDatabase entities = null; + if (!modules.TryGetValue(moduleName, out entities)) + { + entities = new ModuleDatabase(); + modules.Add(moduleName, entities); + } + entities.Add(e.Type.ToFullyQualifiedName(true), e); + } + + Entity EntityFromXElement(XElement entityElem, Dictionary theModules, ErrorHandling errors) + { + var typeDeclElement = entityElem.Element("typedeclaration"); + if (typeDeclElement == null) + { + errors.Add(new ReflectorError(ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 6, "Entity elements must contain a child element."))); + return null; + } + var moduleName = (string)typeDeclElement.Attribute("module"); + if (string.IsNullOrEmpty(moduleName)) + { + errors.Add(new ReflectorError(ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 7, "Entity elements must contain a module name."))); + return null; + } + var module = MakeModuleForName(moduleName, theModules); + var folder = new TypeAliasFolder(module.TypeAliases); + var decl = TypeDeclaration.FromXElement(folder, typeDeclElement, module, null) as TypeDeclaration; + if (decl == null) + { + errors.Add(new ReflectorError(ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 8, "Incorrect type declaration in entity."))); + return null; + } + var e = new Entity + { + SharpNamespace = (string)entityElem.Attribute("sharpNameSpace"), + SharpTypeName = (string)entityElem.Attribute("sharpTypeName"), + EntityType = ToEntityType((string)entityElem.Attribute("entityType")), + ProtocolProxyModule = (string)entityElem.Attribute("protocolProxyModule"), + IsDiscretionaryConstraint = IsDiscetionaryConstraint(entityElem), + Type = decl + }; + if (e.SharpNamespace == null) + { + errors.Add(new ReflectorError(ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 12, "Missing sharpNameSpace in entity."))); + return null; + } + if (e.SharpTypeName == null) + { + errors.Add(new ReflectorError(ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 13, "Missing sharpTypeName in entity."))); + return null; + } + return e; + } + + static EntityType ToEntityType(string s) + { + ArgumentNullException.ThrowIfNull(s, nameof(s)); + switch (s.ToLower()) + { + case "scalar": + return EntityType.Scalar; + case "class": + return EntityType.Class; + case "struct": + return EntityType.Struct; + case "enum": + return EntityType.Enum; + case "trivialenum": + return EntityType.TrivialEnum; + case "protocol": + return EntityType.Protocol; + default: + case "none": + return EntityType.None; + } + } + + static bool IsDiscetionaryConstraint(XElement entityElem) + { + var discretionary = (string)entityElem.Attribute("discretionaryConstraint") ?? "false"; + return discretionary.ToLower() == "true"; + } + + ModuleDeclaration MakeModuleForName(string name, Dictionary modules) + { + ModuleDeclaration module = null; + if (!modules.TryGetValue(name, out module)) + { + module = new ModuleDeclaration(); + module.Name = name; + modules.Add(name, module); + } + return module; + } + } +} + diff --git a/src/SwiftReflector/src/TypeMapping/TypeMapper.cs b/src/SwiftReflector/src/TypeMapping/TypeMapper.cs new file mode 100644 index 000000000000..e5f6da069745 --- /dev/null +++ b/src/SwiftReflector/src/TypeMapping/TypeMapper.cs @@ -0,0 +1,384 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Globalization; +using SwiftReflector.ExceptionTools; +using SwiftReflector.SwiftXmlReflection; +using System.IO; +using SyntaxDynamo.CSLang; +using SwiftRuntimeLibrary; + +namespace SwiftReflector.TypeMapping +{ + public class CSKeywords + { + static HashSet keyWords; + static string[] keyArr = new string[] { + "abstract", "as", "base", "bool", "break", "byte", + "case", "catch", "char", "checked", "class", "const", + "continue", "decimal", "default", "delegate", "do", + "double", "else", "enum", "event", "explicit", "extern", + "false", "finally", "fixed", "float", "for", "foreach", + "goto", "if", "implicit", "in", "int", "interface", "internal", + "is", "lock", "long", "namespace", "new", "null", "object", + "operator", "out", "override", "params", "private", "protected", + "public", "readonly", "ref", "return", "sbyte", "sealed", "short", + "sizeof", "stackalloc", "static", "string", "struct", "switch", + "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", + "unsafe", "ushort", "using", "virtual", "void", "volatile", "while", + "add", "alias", "ascending", "async", "await", "descending", "dynamic", + "from", "get", "global", "group", "into", "join", "let", "orderby", + "partial", "remove", "select", "set", "value", "var", "where", "yield" + }; + static CSKeywords() + { + keyWords = new HashSet(); + foreach (string s in keyArr) + { + keyWords.Add(s); + } + } + + public static bool IsKeyword(string s) + { + ArgumentNullException.ThrowIfNull(s, nameof(s)); + return keyWords.Contains(s); + } + } + + public class TypeMapper + { + public TypeDatabase TypeDatabase { get; private set; } + UnicodeMapper unicodeMapper; + HashSet loadedFiles = new HashSet(); + + public TypeMapper(List typeDatabasePaths, UnicodeMapper unicodeMapper) + { + TypeDatabase = new TypeDatabase(); + this.unicodeMapper = unicodeMapper; + + string basePath = AppDomain.CurrentDomain.BaseDirectory; + string xmlFilePath = Path.Combine(basePath, "SwiftCore.xml"); + AddTypeDatabase(xmlFilePath); + } + + public void AddTypeDatabase(string fileName) + { + if (loadedFiles.Contains(fileName)) + return; + loadedFiles.Add(fileName); + var errors = TypeDatabase.Read(fileName); + if (errors.AnyErrors) + throw new AggregateException(errors.Errors.Select((v) => v.Exception)); + } + + public Entity GetEntityForSwiftClassName(string fullyQualifiedName) + { + return TypeDatabase.EntityForSwiftName(fullyQualifiedName); + } + + public Entity TryGetEntityForSwiftClassName(string fullyQualifiedName) + { + return TypeDatabase.TryGetEntityForSwiftName(fullyQualifiedName); + } + + public Entity GetEntityForTypeSpec(TypeSpec spec) + { + if (spec == null) + return null; + var ns = spec as NamedTypeSpec; + if (ns == null || spec.IsDynamicSelf) + return null; + return GetEntityForSwiftClassName(ns.Name); + } + + public EntityType GetEntityTypeForTypeSpec(TypeSpec spec) + { + if (spec == null) + return EntityType.None; + + if (spec is NamedTypeSpec) + { + if (spec.IsDynamicSelf) + return EntityType.DynamicSelf; + var ent = GetEntityForTypeSpec(spec); + return ent != null ? ent.EntityType : EntityType.None; + } + if (spec is TupleTypeSpec) + { + return EntityType.Tuple; + } + if (spec is ClosureTypeSpec) + { + return EntityType.Closure; + } + if (spec is ProtocolListTypeSpec) + { + return EntityType.ProtocolList; + } + throw new ArgumentOutOfRangeException(spec.GetType().Name); + } + + static string ComeUpWithAName(string given, string typeName, int index) + { + if (String.IsNullOrEmpty(given)) + { + return String.Format("{0}{1}", Char.ToLower(typeName[0]), index); + } + else + { + return given; + } + } + + static NetParam ToNamedParam(ParameterItem st, NetTypeBundle bundle, int index) + { + string targetName = ComeUpWithAName(st.NameIsRequired ? st.PublicName : st.PrivateName, bundle.Type, index); + return new NetParam(targetName, bundle); + } + + static bool IsUnique(NetParam p, List pl, int startPoint) + { + for (int i = startPoint; i < pl.Count; i++) + { + if (p.Name == pl[i].Name) + return false; + } + return true; + } + + static NetParam Uniquify(NetParam p, List pl, int startPoint) + { + while (!IsUnique(p, pl, startPoint) || CSKeywords.IsKeyword(p.Name)) + { + p = new NetParam(p.Name + '0', p.Type); + } + return p; + } + + static List SanitizeParamNames(List parms) + { + List outlist = new List(); + bool changed = false; + do + { + changed = false; + outlist = new List(); + for (int i = 0; i < parms.Count; i++) + { + NetParam q = Uniquify(parms[i], parms, i + 1); + changed = q.Name != parms[i].Name; + outlist.Add(q); + } + if (changed) + parms = outlist; + } while (changed); + return outlist; + } + + NetTypeBundle RecastToReference(BaseDeclaration typeContext, NetTypeBundle netBundle, TypeSpec theElem, bool structsAndEnumsAreAlwaysRefs) + { + var entity = GetEntityForTypeSpec(theElem); + if (entity != null && (entity.IsObjCStruct || entity.IsObjCEnum) && netBundle.IsReference) + return netBundle; + if (theElem.IsInOut && netBundle.Entity != EntityType.Struct) + return netBundle; + var objcStructType = ObjCStructOrEnumReferenceType(typeContext, theElem as NamedTypeSpec); + if (objcStructType != null) + { + return MapType(typeContext, objcStructType, true); + } + if (entity != null && entity.EntityType == EntityType.Protocol && !entity.IsObjCProtocol) + { + return new NetTypeBundle(netBundle.NameSpace, netBundle.Type, netBundle.IsScalar, true, netBundle.Entity); + } + return netBundle; + } + + + NetParam MapParameterItem(BaseDeclaration context, ParameterItem parameter, int index, bool isPinvoke, bool structsAndEnumsAreAlwaysRefs) + { + var theType = parameter.TypeSpec; + var t = MapType(context, theType, isPinvoke); + if (isPinvoke) + { + t = RecastToReference(context, t, theType, structsAndEnumsAreAlwaysRefs); + } + return ToNamedParam(parameter, t, index); + } + + public List MapParameterList(BaseDeclaration context, List st, bool isPinvoke, + bool structsAndEnumsAreAlwaysRefs, CSGenericTypeDeclarationCollection extraProtocolTypes, + CSGenericConstraintCollection extraProtocolContstraints, CSUsingPackages use) + { + var parms = new List(); + for (int i = 0; i < st.Count; i++) + { + var entity = GetEntityForTypeSpec(st[i].TypeSpec); + parms.Add(MapParameterItem(context, st[i], i, isPinvoke, structsAndEnumsAreAlwaysRefs)); + } + return SanitizeParamNames(parms); + } + + public NetTypeBundle MapType(BaseDeclaration context, TypeSpec spec, bool isPinvoke, bool isReturnValue = false, + Tuple selfDepthIndex = null) + { + switch (spec.Kind) + { + case TypeSpecKind.Named: + var named = (NamedTypeSpec)spec; + if (IsScalar(named.Name)) + { + return ToScalar(named.Name, spec.IsInOut); + } + else + { + Entity en = TypeDatabase.EntityForSwiftName(named.Name); + if (en != null) + { + if (isPinvoke) + { + switch (en.EntityType) + { + case EntityType.Scalar: + return new NetTypeBundle(en.SharpNamespace, en.SharpTypeName, false, spec.IsInOut, en.EntityType); + default: + throw ErrorHelper.CreateError(ReflectorError.kCantHappenBase + 21, "Can't happen - shouldn't ever get to this case in type mapping."); + } + } + else + { + var retval = new NetTypeBundle(en.SharpNamespace, en.SharpTypeName, false, spec.IsInOut, en.EntityType); + return retval; + } + } + else + { + if (isPinvoke) + { + var namedSpec = spec as NamedTypeSpec; + if (namedSpec != null) + { + if (TypeMapper.IsSwiftPointerType(namedSpec.Name)) + { + return new NetTypeBundle("System", "IntPtr", false, false, EntityType.None); + } + } + } + throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 0, $"Unable to find C# reference for swift class '{spec.ToString()}'."); + } + } + case TypeSpecKind.Tuple: + var tuple = (TupleTypeSpec)spec; + if (tuple.Elements.Count == 0) + return NetTypeBundle.Void; + var tupTypes = tuple.Elements.Select(ts => MapType(context, ts, isPinvoke)).ToList(); + return new NetTypeBundle(tupTypes, tuple.IsInOut); + default: + throw new NotImplementedException(); + } + } + + TypeSpec ObjCStructOrEnumReferenceType(BaseDeclaration context, NamedTypeSpec spec) + { + var boundType = GetBoundPointerType(spec); + if (boundType == null) + return null; + if (context.IsTypeSpecGenericReference(boundType)) + return null; + if (context.IsProtocolWithAssociatedTypesFullPath(boundType, this)) + return null; + var entity = TypeDatabase.EntityForSwiftName(boundType.Name); + return entity.IsObjCStruct || entity.IsObjCEnum ? boundType : null; + } + + static NamedTypeSpec GetBoundPointerType(NamedTypeSpec spec) + { + if (spec == null) + return null; + if (spec.Name != "Swift.UnsafePointer" && spec.Name != "Swift.UnsafeMutablePointer") + return null; + var boundType = spec.GenericParameters[0] as NamedTypeSpec; + return boundType; + } + + NetTypeBundle ToScalar(SwiftBuiltInType bit) + { + switch (bit.BuiltInType) + { + case CoreBuiltInType.Bool: + return ToScalar("Swift.Bool", bit.IsReference); + case CoreBuiltInType.Double: + return ToScalar("Swift.Double", bit.IsReference); + case CoreBuiltInType.Float: + return ToScalar("Swift.Float", bit.IsReference); + case CoreBuiltInType.Int: + return new NetTypeBundle("System", "nint", true, bit.IsReference, EntityType.Scalar); + case CoreBuiltInType.UInt: + return new NetTypeBundle("System", "nuint", true, bit.IsReference, EntityType.Scalar); + default: + throw new ArgumentOutOfRangeException(nameof(bit)); + } + } + + static string[] scalarNames = new string[] { + "Swift.Bool", + "Swift.Double", + "Swift.Float", + "Swift.Int", + "Swift.UInt", + "Swift.Int8", + "Swift.UInt8", + "Swift.Int16", + "Swift.UInt16", + "Swift.Int32", + "Swift.UInt32", + "Swift.Int64", + "Swift.UInt64" + }; + + static int ScalarIndex(string builtIn) + { + return Array.IndexOf(scalarNames, builtIn); + } + + public static bool IsScalar(string builtIn) + { + ArgumentNullException.ThrowIfNull(builtIn, nameof(builtIn)); + return ScalarIndex(builtIn) >= 0; + } + + public static bool IsScalar(TypeSpec spec) + { + var ns = spec as NamedTypeSpec; + if (ns == null) + return false; + return ScalarIndex(ns.Name) >= 0; + } + + NetTypeBundle ToScalar(string builtIn, bool isReference) + { + int index = ScalarIndex(builtIn); + if (index >= 0) + { + var en = TypeDatabase.EntityForSwiftName(builtIn); + if (en != null) + { + return new NetTypeBundle(en.SharpNamespace, en.SharpTypeName, false, isReference, en.EntityType); + } + } + throw new ArgumentOutOfRangeException(nameof(builtIn)); + } + + public static bool IsSwiftPointerType(string fullTypeName) + { + return fullTypeName == "Swift.UnsafePointer" || fullTypeName == "Swift.UnsafeMutablePointer" + || fullTypeName == "Swift.UnsafeRawPointer" || fullTypeName == "Swift.UnsafeMutableRawPointer"; + } + } +} + diff --git a/src/SwiftReflector/src/UnicodeMapper.cs b/src/SwiftReflector/src/UnicodeMapper.cs new file mode 100644 index 000000000000..67405cf2b435 --- /dev/null +++ b/src/SwiftReflector/src/UnicodeMapper.cs @@ -0,0 +1,124 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; +using System.Xml.Linq; + +namespace SwiftReflector +{ + public sealed class UnicodeMapper + { + + static Dictionary DefaultMapping = new Dictionary { + { "\x03b1", "Alpha" }, + { "\x03b2", "Beta" }, + { "\x03b3", "Gamma" }, + { "\x03b4", "Delta" }, + { "\x03b5", "Epsilon" }, + { "𝑒", "LittleEpsilon"}, + { "Π", "BigPi"}, + { "\x03c0", "Pi" }, + { "𝝉", "Tau"}, + { "\x03c4", "Tau" }, + { "\x00ac", "Not" }, + { "\x2227", "And" }, + { "\x2228", "Or" }, + { "\x22bb", "Xor" }, + { "\x2295", "CirclePlus" }, + { "\x21ae", "NotLeftRightArrow" }, + { "\x2262", "NotIdentical" }, + { "\x22bc", "Nand" }, + { "\x2191", "UpArrow" }, + { "\x22bd", "Nor" }, + { "\x2193", "DownArrow" }, + { "\x22a6", "Assertion" }, + { "\x00f7", "Division" }, + { "\x00d7", "Multiplication" }, + { "\x221a", "SquareRoot" }, + { "\x221b", "CubeRoot" }, + { "\x00b1", "PlusOrMinus" }, + { "\x2213", "MinusOrPlus" }, + { "\x2224", "DoesNotDivide" }, + { "\x2208", "ElementOf" }, + { "\x220c", "NotElementOf" }, + { "\x2229", "Intersection" }, + { "\x222a", "Union" }, + { "\x2286", "Subset" }, + { "\x2282", "ProperSubset" }, + { "\x2284", "NotSubset" }, + { "\x2287", "Superset" }, + { "\x2283", "ProperSuperset" }, + { "\x2285", "NotSuperset" }, + { "\x2264", "LessThanOrEqualTo" }, + { "\x2265", "GreaterThanOrEqualTo" }, + { "\x226c", "Between" }, + { "\x2248", "Approximates" }, + { "\x2218", "Ring" }, + }; + + public static UnicodeMapper Default = new UnicodeMapper(); + + Dictionary mapping; + + public UnicodeMapper() + { + mapping = DefaultMapping; + } + + // While this takes a string, it should be one 'character', possibly made up of multiple + // parts, like 🍎 + public string MapToUnicodeName(string s) + { + if (new StringInfo(s).LengthInTextElements != 1) + throw new ArgumentOutOfRangeException(nameof(s)); + + if (mapping.TryGetValue(s, out var result)) + return result; + + StringBuilder stringBuilder = new StringBuilder().Append("U"); + + var encoding = Encoding.UTF32; + var bytes = encoding.GetBytes(s); + var utf32Value = BitConverter.ToUInt32(bytes, 0); + if (utf32Value > 0xffff) + stringBuilder.Append($"{utf32Value:X8}"); + else + stringBuilder.Append($"{utf32Value:X4}"); + + return stringBuilder.ToString(); + } + + public void AddMappingsFromFile(string fileName) + { + AddMappingsFromXML(File.ReadAllText(fileName)); + } + + public void AddMappingsFromXML(string mappingXML) + { + if (mapping == DefaultMapping) + { + // Clone the default mapping, since we don't want to modify it. + mapping = new Dictionary(mapping); + } + foreach (var m in ReadMappings(mappingXML)) + mapping[m.Item1] = m.Item2; + } + + static IEnumerable> ReadMappings(string mappingXML) + { + XDocument xmlDocument = XDocument.Parse(mappingXML); + foreach (var mapping in xmlDocument.Descendants("map")) + { + string from = mapping.Attribute(XName.Get("from"))?.Value; + string to = mapping.Attribute(XName.Get("to"))?.Value; + + if (from != null && to != null) + yield return new Tuple(from, to); + } + } + } +} diff --git a/src/SwiftReflector/tests/SwiftReflector.Tests.csproj b/src/SwiftReflector/tests/SwiftReflector.Tests.csproj new file mode 100644 index 000000000000..c5b3f2ab03e1 --- /dev/null +++ b/src/SwiftReflector/tests/SwiftReflector.Tests.csproj @@ -0,0 +1,12 @@ + + + + net8.0 + enable + enable + + false + true + + + diff --git a/src/SwiftReflector/tests/UnitTest1.cs b/src/SwiftReflector/tests/UnitTest1.cs new file mode 100644 index 000000000000..58909a7e2c56 --- /dev/null +++ b/src/SwiftReflector/tests/UnitTest1.cs @@ -0,0 +1,12 @@ +using Xunit; + +namespace SwiftReflector.Tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} \ No newline at end of file diff --git a/src/SwiftRuntimeLibrary/src/ISwiftObject.cs b/src/SwiftRuntimeLibrary/src/ISwiftObject.cs new file mode 100644 index 000000000000..1ededa64b6a8 --- /dev/null +++ b/src/SwiftRuntimeLibrary/src/ISwiftObject.cs @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Runtime.InteropServices; + +namespace SwiftRuntimeLibrary +{ + public unsafe interface ISwiftObject : IDisposable + { + void* SwiftObject { get; } + } +} + diff --git a/src/SwiftRuntimeLibrary/src/SwiftCore.xml b/src/SwiftRuntimeLibrary/src/SwiftCore.xml new file mode 100644 index 000000000000..96066ebbbaa3 --- /dev/null +++ b/src/SwiftRuntimeLibrary/src/SwiftCore.xml @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SwiftRuntimeLibrary/src/SwiftRuntimeLibrary.csproj b/src/SwiftRuntimeLibrary/src/SwiftRuntimeLibrary.csproj new file mode 100644 index 000000000000..aa237dc759f5 --- /dev/null +++ b/src/SwiftRuntimeLibrary/src/SwiftRuntimeLibrary.csproj @@ -0,0 +1,14 @@ + + + Library + net8.0 + enable + disable + true + + + + PreserveNewest + + + diff --git a/src/SwiftRuntimeLibrary/tests/SwiftRuntimeLibrary.Tests.csproj b/src/SwiftRuntimeLibrary/tests/SwiftRuntimeLibrary.Tests.csproj new file mode 100644 index 000000000000..c5b3f2ab03e1 --- /dev/null +++ b/src/SwiftRuntimeLibrary/tests/SwiftRuntimeLibrary.Tests.csproj @@ -0,0 +1,12 @@ + + + + net8.0 + enable + enable + + false + true + + + diff --git a/src/SwiftRuntimeLibrary/tests/UnitTest1.cs b/src/SwiftRuntimeLibrary/tests/UnitTest1.cs new file mode 100644 index 000000000000..8130d82463b2 --- /dev/null +++ b/src/SwiftRuntimeLibrary/tests/UnitTest1.cs @@ -0,0 +1,12 @@ +using Xunit; + +namespace SwiftRuntimeLibrary.Tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} \ No newline at end of file diff --git a/src/SyntaxDynamo/src/CodeElementCollection.cs b/src/SyntaxDynamo/src/CodeElementCollection.cs new file mode 100644 index 000000000000..ccdd7fdc369f --- /dev/null +++ b/src/SyntaxDynamo/src/CodeElementCollection.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SyntaxDynamo +{ + public class CodeElementCollection : List, ICodeElementSet where T : ICodeElement + { + public CodeElementCollection() : base() + { + } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public virtual object BeginWrite(ICodeWriter writer) + { + OnBeginWrite(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBeginWrite(WriteEventArgs args) + { + Begin(this, args); + } + + public virtual void Write(ICodeWriter writer, object o) + { + } + + public virtual void EndWrite(ICodeWriter writer, object o) + { + OnEndWrite(new WriteEventArgs(writer)); + } + + protected virtual void OnEndWrite(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + + #endregion + + #region ICodeElemSet implementation + + public System.Collections.Generic.IEnumerable Elements + { + get + { + return this.Cast(); + } + } + + #endregion + + } +} + diff --git a/src/SyntaxDynamo/src/CodeWriter.cs b/src/SyntaxDynamo/src/CodeWriter.cs new file mode 100644 index 000000000000..3b51edacce94 --- /dev/null +++ b/src/SyntaxDynamo/src/CodeWriter.cs @@ -0,0 +1,158 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Globalization; +using System.IO; + +namespace SyntaxDynamo +{ + public class CodeWriter : ICodeWriter + { + int charsWrittenThisLine; + bool indentedThisLine; + + const int kSpacesPerIndent = 4; + const int kWrapPoint = 60; + + public CodeWriter(Stream stm) + : this(new StreamWriter(stm)) + { + } + + public CodeWriter(TextWriter tw) + { + ArgumentNullException.ThrowIfNull(tw, nameof(tw)); + TextWriter = tw; + charsWrittenThisLine = 0; + IndentLevel = 0; + IsAtLineStart = true; + } + + public static void WriteToFile(string fileName, ICodeElement element) + { + using (var stm = new FileStream(fileName, FileMode.Create)) + { + CodeWriter writer = new CodeWriter(stm); + element.WriteAll(writer); + writer.TextWriter.Flush(); + } + } + + public static Stream WriteToStream(ICodeElement element) + { + var stm = new MemoryStream(); + var codeWriter = new CodeWriter(stm); + element.WriteAll(codeWriter); + codeWriter.TextWriter.Flush(); + stm.Flush(); + stm.Seek(0, SeekOrigin.Begin); + return stm; + } + + public static string WriteToString(ICodeElement element) + { + using (var reader = new StreamReader(WriteToStream(element))) + return reader.ReadToEnd(); + } + + public TextWriter TextWriter { get; private set; } + + #region ICodeWriter implementation + + public void BeginNewLine(bool prependIndents) + { + Write(Environment.NewLine, false); + if (prependIndents) + WriteIndents(); + IsAtLineStart = true; + } + + public void EndLine() + { + charsWrittenThisLine = 0; + if (indentedThisLine) + { + indentedThisLine = false; + // strictly speaking, this test shouldn't be necessary + if (IndentLevel > 0) + Exdent(); + } + } + + public bool IsAtLineStart { get; private set; } + + public void Write(string code, bool allowSplit) + { + var characterEnum = StringInfo.GetTextElementEnumerator(code); + while (characterEnum.MoveNext()) + { + string c = characterEnum.GetTextElement(); + WriteUnicode(c, allowSplit); + } + } + + public void Write(char c, bool allowSplit) + { + Write(c.ToString(), allowSplit); + } + + void WriteUnicode(string c, bool allowSplit) + { + var info = new StringInfo(c); + if (info.LengthInTextElements > 1) + throw new ArgumentOutOfRangeException(nameof(c), $"Expected a single unicode value but got '{c}'"); + WriteNoBookKeeping(c); + IsAtLineStart = false; + charsWrittenThisLine++; + if (allowSplit && charsWrittenThisLine > kWrapPoint && IsWhiteSpace(c)) + { + if (!indentedThisLine) + { + Indent(); + indentedThisLine = true; + } + WriteNoBookKeeping(Environment.NewLine); + charsWrittenThisLine = 0; + WriteIndents(); + IsAtLineStart = true; + } + } + + bool IsWhiteSpace(string c) + { + return c.Length == 1 && Char.IsWhiteSpace(c[0]); + + } + + void WriteNoBookKeeping(string s) + { + TextWriter.Write(s); + } + + void WriteIndents() + { + int totalSpaces = IndentLevel * kSpacesPerIndent; + // know what's embarrassing? When your indents cause breaks which generates more indents. + for (int i = 0; i < totalSpaces; i++) + Write(" ", false); + } + + public void Indent() + { + IndentLevel++; + } + + public void Exdent() + { + if (IndentLevel == 0) + throw new Exception("IndentLevel is at 0."); + IndentLevel--; + } + + public int IndentLevel { get; private set; } + + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/CommaListElementCollection.cs b/src/SyntaxDynamo/src/CommaListElementCollection.cs new file mode 100644 index 000000000000..2f4ec9a2141c --- /dev/null +++ b/src/SyntaxDynamo/src/CommaListElementCollection.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo +{ + public class CommaListElementCollection : List, ICodeElement where T : ICodeElement + { + public CommaListElementCollection() + : this("", "") + { + } + + + public CommaListElementCollection(IEnumerable objs) + : this("", "", objs) + { + } + + public CommaListElementCollection(string prefix, string suffix) + : base() + { + ArgumentNullException.ThrowIfNull(prefix, nameof(prefix)); + ArgumentNullException.ThrowIfNull(suffix, nameof(suffix)); + Prefix = prefix; + Suffix = suffix; + } + + public CommaListElementCollection(string prefix, string suffix, IEnumerable objs, bool newlineAfterEach = false) + : this(prefix, suffix) + { + ArgumentNullException.ThrowIfNull(objs, nameof(objs)); + AddRange(objs); + NewlineAfterEach = newlineAfterEach; + } + + + public string Prefix { get; private set; } + public string Suffix { get; private set; } + public bool NewlineAfterEach { get; private set; } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + } + + public void Write(ICodeWriter writer, object o) + { + writer.Write(Prefix, true); + for (int i = 0; i < Count; i++) + { + this[i].WriteAll(writer); + if (i < Count - 1) + writer.Write(", ", true); + if (NewlineAfterEach && !writer.IsAtLineStart) + { + writer.BeginNewLine(true); + } + } + writer.Write(Suffix, true); + } + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + + protected virtual void OnEnd(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/DecoratedCodeElementCollection.cs b/src/SyntaxDynamo/src/DecoratedCodeElementCollection.cs new file mode 100644 index 000000000000..b8420188ace5 --- /dev/null +++ b/src/SyntaxDynamo/src/DecoratedCodeElementCollection.cs @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace SyntaxDynamo +{ + public class DecoratedCodeElementCollection : CodeElementCollection where T : ICodeElement + { + bool startOnOwnLine, endOnOwnLine, indent; + + public DecoratedCodeElementCollection(string startDecoration, string endDecoration, + bool startOnOwnLine, bool endOnOwnLine, bool indent, + IEnumerable elems) + : base() + { + StartDecoration = startDecoration; + EndDecoration = endDecoration; + this.startOnOwnLine = startOnOwnLine; + this.endOnOwnLine = endOnOwnLine; + this.indent = indent; + if (elems != null) + AddRange(elems); + } + + public DecoratedCodeElementCollection(string startDecoration, string endDecoration, + bool startOnOwnLine, bool endOnOwnLine, bool indent) + : this(startDecoration, endDecoration, startOnOwnLine, endOnOwnLine, indent, null) + { + } + + public string StartDecoration { get; private set; } + public string EndDecoration { get; private set; } + + public override void Write(ICodeWriter writer, object o) + { + if (StartDecoration != null) + { + if (startOnOwnLine) + writer.BeginNewLine(true); + writer.Write(StartDecoration, true); + if (startOnOwnLine) + writer.EndLine(); + } + if (indent) + writer.Indent(); + } + + public override void EndWrite(ICodeWriter writer, object o) + { + if (indent) + writer.Exdent(); + if (EndDecoration != null) + { + if (endOnOwnLine) + writer.BeginNewLine(true); + writer.Write(EndDecoration, true); + if (endOnOwnLine) + writer.EndLine(); + } + + base.EndWrite(writer, o); + } + + public override string ToString() + { + return string.Format("{0}{1}{2}", + StartDecoration ?? "", + StartDecoration != null && EndDecoration != null ? "..." : "", + EndDecoration ?? ""); + } + + + public static DecoratedCodeElementCollection CBlock(IEnumerable elems) + { + var col = new DecoratedCodeElementCollection("{", "}", true, true, true); + if (elems != null) + col.AddRange(elems); + return col; + } + } +} + diff --git a/src/SyntaxDynamo/src/DelegatedCommaListElementCollection.cs b/src/SyntaxDynamo/src/DelegatedCommaListElementCollection.cs new file mode 100644 index 000000000000..d6f3e517b3d5 --- /dev/null +++ b/src/SyntaxDynamo/src/DelegatedCommaListElementCollection.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo +{ + public class DelegatedCommaListElemCollection : List, ICodeElement where T : ICodeElement + { + Action elementWriter; + public DelegatedCommaListElemCollection(Action elementWriter) + : base() + { + ArgumentNullException.ThrowIfNull(elementWriter, nameof(elementWriter)); + this.elementWriter = elementWriter; + } + + public DelegatedCommaListElemCollection(Action elementWriter, IEnumerable objs) + : base() + { + ArgumentNullException.ThrowIfNull(elementWriter, nameof(elementWriter)); + ArgumentNullException.ThrowIfNull(objs, nameof(objs)); + this.elementWriter = elementWriter; + AddRange(objs); + } + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + } + + public void Write(ICodeWriter writer, object o) + { + for (int i = 0; i < Count; i++) + { + elementWriter(writer, i, this[i]); + if (i < Count - 1) + writer.Write(", ", true); + } + } + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + + protected virtual void OnEnd(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + } +} + diff --git a/src/SyntaxDynamo/src/DelegatedSimpleElement.cs b/src/SyntaxDynamo/src/DelegatedSimpleElement.cs new file mode 100644 index 000000000000..f3f4df5fee71 --- /dev/null +++ b/src/SyntaxDynamo/src/DelegatedSimpleElement.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo +{ + public abstract class DelegatedSimpleElement : ICodeElement + { + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + } + + public void Write(ICodeWriter writer, object o) + { + LLWrite(writer, o); + } + + protected abstract void LLWrite(ICodeWriter writer, object o); + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + protected virtual void OnEnd(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + } + + public class LineBreak : DelegatedSimpleElement + { + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.EndLine(); + writer.BeginNewLine(true); + } + } +} + diff --git a/src/SyntaxDynamo/src/Extensions.cs b/src/SyntaxDynamo/src/Extensions.cs new file mode 100644 index 000000000000..3fd16f1a6dc2 --- /dev/null +++ b/src/SyntaxDynamo/src/Extensions.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo +{ + public static class Extensions + { + public static void WriteAll(this ICodeElement elem, ICodeWriter writer) + { + object memento = elem.BeginWrite(writer); + elem.Write(writer, memento); + ICodeElementSet set = elem as ICodeElementSet; + if (set != null) + { + foreach (ICodeElement sub in set.Elements) + { + sub.WriteAll(writer); + } + } + elem.EndWrite(writer, memento); + } + + public static void FireInReverse(this EventHandler handler, object sender, EventArgs args) where T : EventArgs + { + var dels = handler.GetInvocationList(); + for (int i = dels.Length - 1; i >= 0; i--) + { + dels[i].DynamicInvoke(new object[] { sender, args }); + } + } + + public static IEnumerable Interleave(this IEnumerable contents, T separator, bool includeSeparatorFirst = false) + { + bool first = true; + foreach (T t in contents) + { + if (!first || includeSeparatorFirst) + yield return separator; + first = false; + yield return t; + } + } + + public static IEnumerable BracketInterleave(this IEnumerable contents, T start, T end, T separator, bool includeSeparatorFirst = false) + { + yield return start; + foreach (T t in contents.Interleave(separator, includeSeparatorFirst)) + yield return t; + yield return end; + } + + public static T AttachBefore(this T attacher, ICodeElement attachTo) where T : ICodeElement + { + ArgumentNullException.ThrowIfNull(attachTo, nameof(attachTo)); + attachTo.Begin += (s, eventArgs) => + { + attacher.WriteAll(eventArgs.Writer); + }; + return attacher; + } + + public static T AttachAfter(this T attacher, ICodeElement attachTo) where T : ICodeElement + { + ArgumentNullException.ThrowIfNull(attachTo, nameof(attachTo)); + attachTo.End += (s, eventArgs) => + { + attacher.WriteAll(eventArgs.Writer); + }; + return attacher; + } + } +} + diff --git a/src/SyntaxDynamo/src/ICodeElement.cs b/src/SyntaxDynamo/src/ICodeElement.cs new file mode 100644 index 000000000000..3346c97dea40 --- /dev/null +++ b/src/SyntaxDynamo/src/ICodeElement.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo +{ + public interface ICodeElement + { + // these three methods represent the memento pattern. The object returned is only ever used by + // the ICodeElem. + object BeginWrite(ICodeWriter writer); + void Write(ICodeWriter writer, object o); + void EndWrite(ICodeWriter writer, object o); + + // These events seem redundant, but they are intended for use for non-structural code elements + // such as block comments or #region or #if/#else/#endif + + // Begin should be fired by BeginWrite BEFORE anything is written + event EventHandler Begin; + // Note, when you implement End, it should use GetInvocationList and fire in reverse order. + // End should be fired by EndWrite AFTER anything is written + event EventHandler End; + } +} + diff --git a/src/SyntaxDynamo/src/ICodeElementSet.cs b/src/SyntaxDynamo/src/ICodeElementSet.cs new file mode 100644 index 000000000000..67f85843db57 --- /dev/null +++ b/src/SyntaxDynamo/src/ICodeElementSet.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace SyntaxDynamo +{ + public interface ICodeElementSet : ICodeElement + { + IEnumerable Elements { get; } + } +} + diff --git a/src/SyntaxDynamo/src/ICodeWriter.cs b/src/SyntaxDynamo/src/ICodeWriter.cs new file mode 100644 index 000000000000..e10015db8fb9 --- /dev/null +++ b/src/SyntaxDynamo/src/ICodeWriter.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo +{ + public interface ICodeWriter + { + void BeginNewLine(bool prependIndents); + void EndLine(); + void Write(char c, bool allowSplit); + void Write(string code, bool allowSplit); + void Indent(); + void Exdent(); + int IndentLevel { get; } + bool IsAtLineStart { get; } + } +} + diff --git a/src/SyntaxDynamo/src/LabeledCodeElementCollection.cs b/src/SyntaxDynamo/src/LabeledCodeElementCollection.cs new file mode 100644 index 000000000000..f0de5ada7e2a --- /dev/null +++ b/src/SyntaxDynamo/src/LabeledCodeElementCollection.cs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo +{ + public class LabeledCodeElementCollection : ICodeElementSet where T : ICodeElement + { + public LabeledCodeElementCollection(SimpleLineElement label, CodeElementCollection block) + { + ArgumentNullException.ThrowIfNull(label, nameof(label)); + ArgumentNullException.ThrowIfNull(block, nameof(block)); + Label = label; + Block = block; + } + + public SimpleLineElement Label { get; private set; } + public CodeElementCollection Block { get; private set; } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + } + + public void Write(ICodeWriter writer, object o) + { + } + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + protected virtual void OnEnd(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + + #region ICodeElemSet implementation + + public IEnumerable Elements + { + get + { + yield return Label; + yield return Block; + } + } + + #endregion + + } +} + diff --git a/src/SyntaxDynamo/src/LineCodeElementCollection.cs b/src/SyntaxDynamo/src/LineCodeElementCollection.cs new file mode 100644 index 000000000000..34ca0376e032 --- /dev/null +++ b/src/SyntaxDynamo/src/LineCodeElementCollection.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace SyntaxDynamo +{ + public class LineCodeElementCollection : CodeElementCollection where T : ICodeElement + { + bool indent, prependIndents, isSingleLine; + public LineCodeElementCollection(IEnumerable elems, bool indent, bool prependIndents) + : this(elems, true, indent, prependIndents) + { + } + + public LineCodeElementCollection(bool isSingleLine, bool indent, bool prependIndents) + : this(null, isSingleLine, indent, prependIndents) + { + } + + public LineCodeElementCollection(IEnumerable elems, bool isSingleLine, bool indent, bool prependIndents) + { + this.isSingleLine = isSingleLine; + this.indent = indent; + this.prependIndents = prependIndents; + if (elems != null) + AddRange(elems); + } + + + public override void Write(ICodeWriter writer, object o) + { + if (isSingleLine) + { + if (indent) + writer.Indent(); + writer.BeginNewLine(prependIndents); + } + } + + protected override void OnEndWrite(WriteEventArgs args) + { + if (isSingleLine) + args.Writer.EndLine(); + base.OnEndWrite(args); + } + + public LineCodeElementCollection And(T elem) + { + Add(elem); + return this; + } + + } +} + diff --git a/src/SyntaxDynamo/src/SimpleElement.cs b/src/SyntaxDynamo/src/SimpleElement.cs new file mode 100644 index 000000000000..015f5dca3148 --- /dev/null +++ b/src/SyntaxDynamo/src/SimpleElement.cs @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo +{ + public class SimpleElement : ICodeElement + { + bool allowSplit; + public SimpleElement(string label, bool allowSplit = false) + { + Label = label; + this.allowSplit = allowSplit; + } + + public string Label { get; private set; } + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + } + + public void Write(ICodeWriter writer, object o) + { + writer.Write(Label, allowSplit); + } + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + protected virtual void OnEnd(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + + public override string ToString() + { + return Label; + } + + static SimpleElement spacer = new SimpleElement(" ", true); + public static SimpleElement Spacer { get { return spacer; } } + } +} + diff --git a/src/SyntaxDynamo/src/SimpleLineElement.cs b/src/SyntaxDynamo/src/SimpleLineElement.cs new file mode 100644 index 000000000000..fac2ca831a64 --- /dev/null +++ b/src/SyntaxDynamo/src/SimpleLineElement.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo +{ + public class SimpleLineElement : ICodeElement + { + bool indent, prependIndents, allowSplit; + + public SimpleLineElement(string contents, bool indent, bool prependIdents, bool allowSplit) + { + Contents = contents ?? ""; + this.indent = indent; + this.prependIndents = prependIdents; + this.allowSplit = allowSplit; + } + + public string Contents { get; private set; } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + } + + public void Write(ICodeWriter writer, object o) + { + if (indent) + writer.Indent(); + writer.BeginNewLine(prependIndents); + writer.Write(Contents, allowSplit); + writer.EndLine(); + } + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + protected virtual void OnEnd(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + + public override string ToString() + { + return Contents; + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSArgument.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSArgument.cs new file mode 100644 index 000000000000..7f039b51daa3 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSArgument.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SyntaxDynamo.CSLang +{ + public class CSArgument : DelegatedSimpleElement + { + public CSArgument(ICSExpression expr) + { + ArgumentNullException.ThrowIfNull(expr, nameof(expr)); + Value = expr; + } + + public ICSExpression Value { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + Value.WriteAll(writer); + } + } + + public class CSArgumentList : CommaListElementCollection + { + + public void Add(ICSExpression expr) + { + Add(new CSArgument(expr)); + } + + public static CSArgumentList FromExpressions(params ICSExpression[] exprs) + { + var al = new CSArgumentList(); + foreach (var ex in exprs) + al.Add(new CSArgument(ex)); + return al; + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSArray1D.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSArray1D.cs new file mode 100644 index 000000000000..4ac2d473c104 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSArray1D.cs @@ -0,0 +1,123 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSArray1D : CSBaseExpression + { + public CSArray1D(CSIdentifier name, CommaListElementCollection paramList) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + ArgumentNullException.ThrowIfNull(paramList, nameof(paramList)); + Name = name; + Parameters = paramList; + } + + public CSArray1D(string name, params CSBaseExpression[] parameters) + : this(new CSIdentifier(name), new CommaListElementCollection(parameters)) + { + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + Name.WriteAll(writer); + writer.Write("[", false); + Parameters.WriteAll(writer); + writer.Write("]", false); + } + + public CSIdentifier Name { get; private set; } + public CommaListElementCollection Parameters { get; private set; } + + public static CSArray1D New(CSSimpleType type, bool isStackAlloc, params CSBaseExpression[] parameters) + { + string ID = (isStackAlloc ? "stackalloc " : "new ") + type.Name; + return new CSArray1D(ID, parameters); + } + } + + public class CSArray1DInitialized : CSBaseExpression + { + public CSArray1DInitialized(CSType type, CommaListElementCollection initializers) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(initializers, nameof(initializers)); + Type = type; + Parameters = initializers; + } + + public CSArray1DInitialized(CSType type, params CSBaseExpression[] parameters) + : this(type, new CommaListElementCollection(parameters)) + { + } + + public CSArray1DInitialized(string typeName, params CSBaseExpression[] parameters) + : this(new CSSimpleType(typeName), new CommaListElementCollection(parameters)) + { + } + + public CSArray1DInitialized(string typeName, IEnumerable parameters) + : this(new CSSimpleType(typeName), new CommaListElementCollection(parameters)) + { + } + + public CSType Type { get; private set; } + public CommaListElementCollection Parameters { get; private set; } + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write("new ", true); + Type.WriteAll(writer); + writer.Write("[", false); + writer.Write("] ", true); + writer.Write("{ ", true); + Parameters.WriteAll(writer); + writer.Write("}", false); + } + + } + + public class CSListInitialized : CSBaseExpression + { + public CSListInitialized(CSType type, CommaListElementCollection initializers) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(initializers, nameof(initializers)); + Type = type; + Parameters = initializers; + } + + public CSListInitialized(CSType type, params CSBaseExpression[] parameters) + : this(type, new CommaListElementCollection(parameters)) + { + } + + public CSListInitialized(string typeName, params CSBaseExpression[] parameters) + : this(new CSSimpleType(typeName), new CommaListElementCollection(parameters)) + { + } + + public CSListInitialized(string typeName, IEnumerable parameters) + : this(new CSSimpleType(typeName), new CommaListElementCollection(parameters)) + { + } + + public CSType Type { get; private set; } + public CommaListElementCollection Parameters { get; private set; } + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write("new List<", true); + Type.WriteAll(writer); + writer.Write(">", true); + writer.Write("(", false); + writer.Write(") ", true); + writer.Write("{ ", true); + Parameters.WriteAll(writer); + writer.Write("}", false); + } + + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSAssignment.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSAssignment.cs new file mode 100644 index 000000000000..4f84f8e97d9c --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSAssignment.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSAssignment : CSBaseExpression, ICSLineable + { + public CSAssignment(CSBaseExpression lhs, CSAssignmentOperator op, CSBaseExpression rhs) + { + ArgumentNullException.ThrowIfNull(lhs, nameof(lhs)); + ArgumentNullException.ThrowIfNull(rhs, nameof(rhs)); + Target = lhs; + Value = rhs; + Operation = op; + } + + public CSAssignment(string lhs, CSAssignmentOperator op, CSBaseExpression rhs) + : this(new CSIdentifier(lhs), op, rhs) + { + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + Target.WriteAll(writer); + writer.Write(string.Format(" {0} ", ToAssignmentOpString(Operation)), true); + Value.WriteAll(writer); + } + + public CSBaseExpression Target { get; private set; } + public CSBaseExpression Value { get; private set; } + public CSAssignmentOperator Operation { get; private set; } + + static string ToAssignmentOpString(CSAssignmentOperator op) + { + switch (op) + { + case CSAssignmentOperator.Assign: + return "="; + case CSAssignmentOperator.AddAssign: + return "+="; + case CSAssignmentOperator.SubAssign: + return "-="; + case CSAssignmentOperator.MulAssign: + return "*="; + case CSAssignmentOperator.DivAssign: + return "/="; + case CSAssignmentOperator.ModAssign: + return "%="; + case CSAssignmentOperator.AndAssign: + return "&="; + case CSAssignmentOperator.OrAssign: + return "|="; + case CSAssignmentOperator.XorAssign: + return "^="; + default: + throw new ArgumentOutOfRangeException("op"); + } + } + + public static CSLine Assign(string name, CSAssignmentOperator op, CSBaseExpression value) + { + return new CSLine(new CSAssignment(name, op, value)); + } + + public static CSLine Assign(string name, CSBaseExpression value) + { + return Assign(name, CSAssignmentOperator.Assign, value); + } + + public static CSLine Assign(CSBaseExpression name, CSBaseExpression value) + { + return Assign(name, CSAssignmentOperator.Assign, value); + } + + public static CSLine Assign(CSBaseExpression name, CSAssignmentOperator op, CSBaseExpression value) + { + return new CSLine(new CSAssignment(name, op, value)); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSAttribute.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSAttribute.cs new file mode 100644 index 000000000000..413a96413e35 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSAttribute.cs @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Runtime.InteropServices; + +namespace SyntaxDynamo.CSLang +{ + public class CSAttribute : LineCodeElementCollection + { + public CSAttribute(CSIdentifier name, CSArgumentList args, bool isSingleLine = false, bool isReturn = false) + : base(isSingleLine, false, isSingleLine) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Add(new SimpleElement("[")); + if (isReturn) + Add(new SimpleElement("return:")); + Add(name); + if (args != null) + { + Add(new SimpleElement("(")); + Add(args); + Add(new SimpleElement(")")); + } + Add(new SimpleElement("]")); + } + + public CSAttribute(string name, CSArgumentList args) + : this(new CSIdentifier(name), args) + { + } + + public CSAttribute(string name, params ICSExpression[] exprs) + : this(new CSIdentifier(name), CSArgumentList.FromExpressions(exprs)) + { + } + + // DllImport("msvcrt.dll", EntryPoint="puts") + public static CSAttribute DllImport(string dllName, string entryPoint = null) + { + CSArgumentList args = new CSArgumentList(); + args.Add(CSConstant.Val(dllName)); + if (entryPoint != null) + args.Add(new CSAssignment("EntryPoint", CSAssignmentOperator.Assign, CSConstant.Val(entryPoint))); + return new CSAttribute(new CSIdentifier("DllImport"), args, true); + } + + public static CSAttribute DllImport(CSBaseExpression dllName, string entryPoint = null) + { + CSArgumentList args = new CSArgumentList(); + args.Add(dllName); + if (entryPoint != null) + args.Add(new CSAssignment("EntryPoint", CSAssignmentOperator.Assign, CSConstant.Val(entryPoint))); + return new CSAttribute(new CSIdentifier("DllImport"), args, true); + } + + public static CSAttribute UnmanagedCallConv(string callconv) + { + CSArgumentList args = new CSArgumentList(); + + args.Add(new CSAssignment("CallConvs", CSAssignmentOperator.Assign, new CSIdentifier("new Type[] { typeof("+callconv+") }"))); + return new CSAttribute(new CSIdentifier("UnmanagedCallConv"), args, true); + } + + static CSAttribute returnMarshalAsI1 = new CSAttribute("return: MarshalAs", new CSIdentifier("UnmanagedType.I1")); + + public static CSAttribute ReturnMarshalAsI1 => returnMarshalAsI1; + + public static CSAttribute FieldOffset(int offset) + { + CSArgumentList args = new CSArgumentList(); + args.Add(CSConstant.Val(offset)); + return new CSAttribute(new CSIdentifier("FieldOffset"), args, true); + } + + public static CSAttribute LayoutKind(LayoutKind layout) + { + CSArgumentList args = new CSArgumentList(); + args.Add(new CSIdentifier(String.Format("LayoutKind.{0}", layout))); + return new CSAttribute(new CSIdentifier("StructLayout"), args, true); + } + + public static CSAttribute FromAttr(Type attribute, CSArgumentList args, bool isSingleLine = false, bool isReturn = false) + { + ArgumentNullException.ThrowIfNull(attribute, nameof(attribute)); + if (!attribute.IsSubclassOf(typeof(Attribute))) + throw new ArgumentException(String.Format("Type {0} is not an Attribute type.", attribute.Name), nameof(attribute)); + var name = attribute.Name.EndsWith("Attribute") ? + attribute.Name.Substring(0, attribute.Name.Length - "Attribute".Length) : attribute.Name; + return new CSAttribute(new CSIdentifier(name), args, isSingleLine, isReturn); + } + + public static CSAttribute MarshalAsFunctionPointer() + { + CSArgumentList list = new CSArgumentList(); + list.Add(new CSArgument(new CSIdentifier("UnmanagedType.FunctionPtr"))); + return FromAttr(typeof(MarshalAsAttribute), list, false); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBaseExpression.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBaseExpression.cs new file mode 100644 index 000000000000..5c6cf0425409 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBaseExpression.cs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public abstract class CSBaseExpression : DelegatedSimpleElement, ICSExpression + { + public CSBaseExpression Dot(CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Dot, this, rhs); + } + public static CSBaseExpression operator +(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Add, lhs, rhs); + } + public static CSBaseExpression operator -(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Sub, lhs, rhs); + } + public static CSBaseExpression operator *(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Mul, lhs, rhs); + } + public static CSBaseExpression operator /(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Div, lhs, rhs); + } + public static CSBaseExpression operator %(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Mod, lhs, rhs); + } + public static CSBaseExpression operator <(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Less, lhs, rhs); + } + public static CSBaseExpression operator >(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Greater, lhs, rhs); + } + public static CSBaseExpression operator ==(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.Equal, lhs, rhs); + } + public static CSBaseExpression operator !=(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.NotEqual, lhs, rhs); + } + public static CSBaseExpression operator <=(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.LessEqual, lhs, rhs); + } + public static CSBaseExpression operator >=(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.GreaterEqual, lhs, rhs); + } + public static CSBaseExpression operator &(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.BitAnd, lhs, rhs); + } + public static CSBaseExpression operator |(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.BitOr, lhs, rhs); + } + public static CSBaseExpression operator ^(CSBaseExpression lhs, CSBaseExpression rhs) + { + return new CSBinaryExpression(CSBinaryOperator.BitXor, lhs, rhs); + } + public static CSBaseExpression operator <<(CSBaseExpression lhs, int bits) + { + return new CSBinaryExpression(CSBinaryOperator.LeftShift, lhs, CSConstant.Val(bits)); + } + public static CSBaseExpression operator >>(CSBaseExpression lhs, int bits) + { + return new CSBinaryExpression(CSBinaryOperator.RightShift, lhs, CSConstant.Val(bits)); + } + public override bool Equals(object obj) + { + if (obj == null || GetType() != obj.GetType()) + { + return false; + } + + // Add your custom equality logic here + + return base.Equals(obj); + } + + public override int GetHashCode() + { + // Add your custom hash code logic here + + return base.GetHashCode(); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBinaryExpression.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBinaryExpression.cs new file mode 100644 index 000000000000..64eea92012d6 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBinaryExpression.cs @@ -0,0 +1,85 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + + +namespace SyntaxDynamo.CSLang +{ + public class CSBinaryExpression : CSBaseExpression + { + public CSBinaryExpression(CSBinaryOperator op, ICSExpression lhs, ICSExpression rhs) + { + ArgumentNullException.ThrowIfNull(lhs, nameof(lhs)); + ArgumentNullException.ThrowIfNull(rhs, nameof(rhs)); + Operation = op; + Left = lhs; + Right = rhs; + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + Left.WriteAll(writer); + writer.Write(string.Format(Operation == CSBinaryOperator.Dot ? "{0}" : " {0} ", OpToString(Operation)), true); + Right.WriteAll(writer); + } + + public CSBinaryOperator Operation { get; private set; } + public ICSExpression Left { get; private set; } + public ICSExpression Right { get; private set; } + + static string OpToString(CSBinaryOperator op) + { + switch (op) + { + case CSBinaryOperator.Add: + return "+"; + case CSBinaryOperator.Sub: + return "-"; + case CSBinaryOperator.Mul: + return "*"; + case CSBinaryOperator.Div: + return "/"; + case CSBinaryOperator.Mod: + return "%"; + case CSBinaryOperator.And: + return "&&"; + case CSBinaryOperator.Or: + return "||"; + case CSBinaryOperator.Less: + return "<"; + case CSBinaryOperator.Greater: + return ">"; + case CSBinaryOperator.Equal: + return "=="; + case CSBinaryOperator.NotEqual: + return "!="; + case CSBinaryOperator.LessEqual: + return "<="; + case CSBinaryOperator.GreaterEqual: + return ">="; + case CSBinaryOperator.BitAnd: + return "&"; + case CSBinaryOperator.BitOr: + return "|"; + case CSBinaryOperator.BitXor: + return "^"; + case CSBinaryOperator.LeftShift: + return ">>"; + case CSBinaryOperator.RightShift: + return "<<"; + case CSBinaryOperator.Dot: + return "."; + case CSBinaryOperator.Is: + return "is"; + case CSBinaryOperator.As: + return "as"; + case CSBinaryOperator.NullCoalesce: + return "??"; + default: + throw new ArgumentOutOfRangeException("op"); + } + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBinding.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBinding.cs new file mode 100644 index 000000000000..b2a5e7c59461 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSBinding.cs @@ -0,0 +1,84 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Linq; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSBinding : ICodeElementSet + { + public CSBinding(CSIdentifier name, ICSExpression val = null, bool onOwnLine = false) + { + Name = name; + Value = val; + OnOwnLine = onOwnLine; + } + + public CSBinding(string name, ICSExpression val = null, bool onOwnLine = false) + : this(new CSIdentifier(name), val, onOwnLine) + { + } + + public CSIdentifier Name { get; private set; } + public ICSExpression Value { get; private set; } + public bool OnOwnLine { get; private set; } + + public override string ToString() + { + return string.Format("{0}{1}{2}", + Name.Name, Value == null ? "" : " = ", Value == null ? "" : Value.ToString()); + } + + + #region ICodeElem implementation + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + if (OnOwnLine) + args.Writer.BeginNewLine(true); + } + + public void Write(ICodeWriter writer, object o) + { + } + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + protected virtual void OnEnd(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + #endregion + + #region ICodeElemSet implementation + public IEnumerable Elements + { + get + { + yield return Name; + if (Value != null) + { + yield return new SimpleElement(" = ", true); + yield return Value; + } + } + } + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSClass.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSClass.cs new file mode 100644 index 000000000000..680b4773c410 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSClass.cs @@ -0,0 +1,219 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSClass : ICodeElementSet, ICSTopLevelDeclaration + { + public CSClass(CSVisibility vis, CSIdentifier name, IEnumerable methods = null, + bool isStatic = false, bool isSealed = false) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Visibility = vis; + IsStatic = isStatic; + IsSealed = isSealed; + Name = name; + Inheritance = new CSInheritance(); + Delegates = new List(); + Fields = new List(); + Constructors = new List(); + Methods = new List(); + Properties = new List(); + InnerClasses = new CSClasses(); + InnerEnums = new List(); + StaticConstructor = new CSCodeBlock(); + GenericParams = new CSGenericTypeDeclarationCollection(); + GenericConstraints = new CSGenericConstraintCollection(); + + if (methods != null) + Methods.AddRange(methods); + } + + public CSClass(CSVisibility vis, string name, + IEnumerable members = null, bool isStatic = false, bool isSealed = false) + : this(vis, new CSIdentifier(name), members, isStatic, isSealed) + { + } + + protected virtual string EntityLabel { get { return "class"; } } + + public CSVisibility Visibility { get; private set; } + public bool IsStatic { get; private set; } + public bool IsSealed { get; private set; } + public CSIdentifier Name { get; private set; } + public CSInheritance Inheritance { get; private set; } + public List Delegates { get; private set; } + public List Fields { get; private set; } + public List Constructors { get; private set; } + public List Methods { get; private set; } + public List Properties { get; private set; } + public CSClasses InnerClasses { get; private set; } + public List InnerEnums { get; private set; } + public CSCodeBlock StaticConstructor { get; private set; } + public CSGenericTypeDeclarationCollection GenericParams { get; private set; } + public CSGenericConstraintCollection GenericConstraints { get; private set; } + + public CSType ToCSType(IEnumerable genericReplacements) + { + List replacements = genericReplacements.ToList(); + if (replacements.Count < GenericParams.Count) + { + replacements.AddRange(GenericParams.Skip(replacements.Count).Select(gen => new CSSimpleType(gen.Name.Name))); + } + CSSimpleType t = new CSSimpleType(Name.Name, false, replacements.ToArray()); + return t; + } + + public CSType ToCSType() + { + return ToCSType(GenericParams.Select(gen => new CSSimpleType(gen.Name.Name))); + } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public virtual object BeginWrite(ICodeWriter writer) + { + OnBeginWrite(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBeginWrite(WriteEventArgs args) + { + Begin(this, args); + } + + public virtual void Write(ICodeWriter writer, object o) + { + } + + public virtual void EndWrite(ICodeWriter writer, object o) + { + OnEndWrite(new WriteEventArgs(writer)); + } + + protected virtual void OnEndWrite(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + + #region ICodeElemSet implementation + + public IEnumerable Elements + { + get + { + var decl = new LineCodeElementCollection(true, false, true); + if (Visibility != CSVisibility.None) + decl.Add(new SimpleElement(CSMethod.VisibilityToString(Visibility) + " ")); + if (IsStatic) + decl.Add(new SimpleElement("static ", true)); + if (IsSealed) + decl.Add(new SimpleElement("sealed ", true)); + decl.Add(new CSIdentifier(EntityLabel + " ")); + decl.Add(Name); + decl.Add(GenericParams); + if (Inheritance.Count > 0) + { + decl.Add(new SimpleElement(" : ", true)); + decl.Add(Inheritance); + } + if (GenericConstraints.Count > 0) + { + decl.Add(SimpleElement.Spacer); + decl.Add(GenericConstraints); + } + yield return decl; + + var contents = new DecoratedCodeElementCollection("{", "}", + true, true, true); + + contents.AddRange(Delegates); + contents.AddRange(Fields); + + if (StaticConstructor.Count > 0) + { + var m = new CSMethod(CSVisibility.None, CSMethodKind.Static, + null, Name, new CSParameterList(), StaticConstructor); + contents.Add(m); + } + contents.AddRange(Constructors); + contents.AddRange(Methods); + contents.AddRange(Properties); + contents.Add(InnerClasses); + contents.AddRange(InnerEnums); + + yield return contents; + + } + } + + #endregion + } + + public class CSClasses : CodeElementCollection + { + public CSClasses(IEnumerable classes = null) + : base() + { + if (classes != null) + AddRange(classes); + } + + public CSClasses And(CSClass use) + { + Add(use); + return this; + } + } + + public class CSStruct : CSClass + { + public CSStruct(CSVisibility vis, CSIdentifier name, IEnumerable methods = null, + bool isStatic = false, bool isSealed = false) + : base(vis, name, methods, isStatic, isSealed) + { + } + + public CSStruct(CSVisibility vis, string name, + IEnumerable members = null, bool isStatic = false, bool isSealed = false) + : this(vis, new CSIdentifier(name), members, isStatic, isSealed) + { + } + + protected override string EntityLabel + { + get + { + return "struct"; + } + } + } + + public class CSStructs : CodeElementCollection + { + public CSStructs(IEnumerable structs = null) + : base() + { + if (structs != null) + AddRange(structs); + } + + public CSStructs And(CSStruct st) + { + Add(st); + return this; + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSCodeBlock.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSCodeBlock.cs new file mode 100644 index 000000000000..59546585ad24 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSCodeBlock.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSCodeBlock : DecoratedCodeElementCollection, ICSStatement + { + public CSCodeBlock() + : this(null) + { + + } + + public CSCodeBlock(IEnumerable statements) + : this("{", "}", statements) + { + } + + public static CSCodeBlock Create(params ICodeElement[] statements) + { + return new CSCodeBlock(statements); + } + + public CSCodeBlock(string start, string end, IEnumerable statements) + : base(start, end, true, true, true) + { + if (statements != null) + { + foreach (ICodeElement elem in statements) + { + And(elem); + } + } + } + + public CSCodeBlock And(ICodeElement elem) + { + if (!(elem is ICSStatement)) + throw new ArgumentException($"contents must each be an IStatement, got {elem.GetType()}"); + Add(elem); + return this; + } + } + + public class CSUnsafeCodeBlock : CSCodeBlock + { + public CSUnsafeCodeBlock(IEnumerable statements) + : base("unsafe {", "}", statements) + { + } + } + +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSComment.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSComment.cs new file mode 100644 index 000000000000..abd5036b0809 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSComment.cs @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSComment : SimpleLineElement + { + public CSComment(string text) + : base(Commentize(text), false, true, false) + { + } + + static string Commentize(string text) + { + text = text ?? ""; + if (text.Contains("\n")) + throw new ArgumentException("Comment text must not contain new line characters.", "text"); + return "// " + text; + } + } + + public class CSCommentBlock : CodeElementCollection + { + public CSCommentBlock(params CSComment[] comments) + { + AddRange(comments); + } + + public CSCommentBlock(params string[] text) + { + ArgumentNullException.ThrowIfNull(text, nameof(text)); + AddRange(Sanitize(text)); + } + + static IEnumerable Sanitize(string[] text) + { + foreach (string s in text) + { + string[] lines = s.Split('\n'); + foreach (string line in lines) + yield return new CSComment(line); + } + } + + public CSCommentBlock And(string text) + { + AddRange(Sanitize(new string[] { text })); + return this; + } + + public CSCommentBlock And(CSComment comment) + { + ArgumentNullException.ThrowIfNull(comment, nameof(comment)); + Add(comment); + return this; + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSConditionalCompilation.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSConditionalCompilation.cs new file mode 100644 index 000000000000..f707134431a4 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSConditionalCompilation.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSConditionalCompilation : LineCodeElementCollection + { + CSConditionalCompilation(CSIdentifier tag, CSIdentifier condition) + : base(true, false, false) + { + Add(tag); + if ((object)condition != null) + { + Add(SimpleElement.Spacer); + Add(condition); + } + } + + + static CSConditionalCompilation _else = new CSConditionalCompilation(new CSIdentifier("#else"), null); + public static CSConditionalCompilation Else { get { return _else; } } + static CSConditionalCompilation _endif = new CSConditionalCompilation(new CSIdentifier("#endif"), null); + public static CSConditionalCompilation Endif { get { return _endif; } } + + public static CSConditionalCompilation If(CSIdentifier condition) + { + ArgumentNullException.ThrowIfNull(condition, nameof(condition)); + return new CSConditionalCompilation(new CSIdentifier("#if"), condition); + } + + public static void ProtectWithIfEndif(CSIdentifier condition, ICodeElement elem) + { + var @if = If(condition); + @if.AttachBefore(elem); + Endif.AttachAfter(elem); + } + } +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSConstant.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSConstant.cs new file mode 100644 index 000000000000..b5de9d544dfd --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSConstant.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; +using System.IO; +using System.CodeDom.Compiler; +using System.CodeDom; + +namespace SyntaxDynamo.CSLang +{ + public class CSConstant : CSBaseExpression + { + public CSConstant(string val) + { + ArgumentNullException.ThrowIfNull(val, nameof(val)); + Value = val; + } + + public static explicit operator CSConstant(string val) + { + return new CSConstant(val); + } + + public string Value { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write(Value, false); + } + + public static CSConstant Val(byte b) { return new CSConstant(b.ToString()); } + public static CSConstant Val(sbyte sb) { return new CSConstant(sb.ToString()); } + public static CSConstant Val(ushort us) { return new CSConstant(us.ToString()); } + public static CSConstant Val(short s) { return new CSConstant(s.ToString()); } + public static CSConstant Val(uint ui) { return new CSConstant(ui.ToString()); } + public static CSConstant Val(int i) { return new CSConstant(i.ToString()); } + public static CSConstant Val(ulong ul) { return new CSConstant(ul.ToString()); } + public static CSConstant Val(long l) { return new CSConstant(l.ToString()); } + public static CSConstant Val(float f) + { + return new CSConstant(f.ToString() + "f"); + } + public static CSConstant Val(double d) { return new CSConstant(d.ToString()); } + public static CSConstant Val(bool b) { return new CSConstant(b ? "true" : "false"); } + public static CSConstant Val(char c) { return new CSConstant(ToCharLiteral(c)); } + public static CSConstant Val(string s) { return new CSConstant(ToStringLiteral(s)); } + static CSConstant cNull = new CSConstant("null"); + public static CSConstant Null { get { return cNull; } } + static CSConstant cIntPtrZero = new CSConstant("IntPtr.Zero"); + public static CSConstant IntPtrZero { get { return cIntPtrZero; } } + public static CSBaseExpression ValNFloat(double d) { return new CSCastExpression(CSSimpleType.NFloat, Val(d)); } + + static string ToCharLiteral(char c) + { + using (var writer = new StringWriter()) + { + using (var provider = CodeDomProvider.CreateProvider("CSharp")) + { + provider.GenerateCodeFromExpression(new CodePrimitiveExpression(c), writer, null); + return writer.ToString(); + } + } + } + + static string ToStringLiteral(string s) + { + using (var writer = new StringWriter()) + { + using (var provider = CodeDomProvider.CreateProvider("CSharp")) + { + provider.GenerateCodeFromExpression(new CodePrimitiveExpression(s), writer, null); + return writer.ToString(); + } + } + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSDelegateTypeDecl.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSDelegateTypeDecl.cs new file mode 100644 index 000000000000..d2d9ea342d05 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSDelegateTypeDecl.cs @@ -0,0 +1,44 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSDelegateTypeDecl : DelegatedSimpleElement, ICSStatement + { + public CSDelegateTypeDecl(CSVisibility vis, CSType type, CSIdentifier name, CSParameterList parms, bool isUnsafe = false) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Visibility = vis; + Type = type != null ? type : CSSimpleType.Void; + Name = name; + Parameters = parms; + IsUnsafe = isUnsafe; + } + + public CSVisibility Visibility { get; private set; } + public CSType Type { get; private set; } + public CSIdentifier Name { get; private set; } + public CSParameterList Parameters { get; private set; } + public bool IsUnsafe { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.BeginNewLine(true); + writer.Write(CSMethod.VisibilityToString(Visibility), false); + if (IsUnsafe) + writer.Write(" unsafe", true); + writer.Write(" delegate ", true); + Type.WriteAll(writer); + writer.Write(' ', true); + Name.WriteAll(writer); + writer.Write('(', true); + Parameters.WriteAll(writer); + writer.Write(')', true); + writer.Write(';', false); + writer.EndLine(); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSEnum.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSEnum.cs new file mode 100644 index 000000000000..934f0fb9e68d --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSEnum.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SyntaxDynamo.CSLang +{ + public class CSEnum : ICodeElementSet, ICSTopLevelDeclaration + { + public CSEnum(CSVisibility vis, CSIdentifier name, CSType optionalType) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Values = new List(); + Name = name; + OptionalType = optionalType; + Visibility = vis; + } + + public CSEnum(CSVisibility vis, string name, CSType optionalType) + : this(vis, new CSIdentifier(name), optionalType) + { + } + + public List Values { get; private set; } + public CSVisibility Visibility { get; private set; } + public CSType OptionalType { get; private set; } + public CSIdentifier Name { get; private set; } + + public CSType ToCSType() + { + return new CSSimpleType(Name.Name); + } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public virtual object BeginWrite(ICodeWriter writer) + { + OnBeginWrite(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBeginWrite(WriteEventArgs args) + { + Begin(this, args); + } + + public virtual void Write(ICodeWriter writer, object o) + { + } + + public virtual void EndWrite(ICodeWriter writer, object o) + { + OnEndWrite(new WriteEventArgs(writer)); + } + + protected virtual void OnEndWrite(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + + #region ICodeElemSet implementation + + public IEnumerable Elements + { + get + { + var decl = new LineCodeElementCollection(true, false, true); + if (Visibility != CSVisibility.None) + decl.Add(new SimpleElement(CSMethod.VisibilityToString(Visibility) + " ")); + decl.Add(new CSIdentifier("enum" + " ")); + decl.Add(Name); + + if (OptionalType != null) + { + decl.Add(new SimpleElement(" : ", true)); + decl.Add(OptionalType); + } + yield return decl; + + var contents = new DecoratedCodeElementCollection("{", "}", + true, true, true); + + var bindings = new CommaListElementCollection(); + bindings.AddRange(Values); + if (bindings.Count > 0 && !bindings[0].OnOwnLine) + { + bindings[0] = new CSBinding(bindings[0].Name, bindings[0].Value, true); + } + contents.Add(bindings); + + yield return contents; + + } + } + + #endregion + + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFieldDeclaration.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFieldDeclaration.cs new file mode 100644 index 000000000000..b4fc99e0abe7 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFieldDeclaration.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSVariableDeclaration : LineCodeElementCollection, ICSExpression, ICSLineable + { + public CSVariableDeclaration(CSType type, IEnumerable bindings) + : base(null, false, true) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(bindings, nameof(bindings)); + Type = type; + And(Type).And(SimpleElement.Spacer); + Bindings = new CommaListElementCollection(bindings); + Add(Bindings); + } + + public CSVariableDeclaration(CSType type, string name, ICSExpression value = null) + : this(type, new CSIdentifier(name), value) + { + } + + public CSVariableDeclaration(CSType type, CSIdentifier name, ICSExpression value = null) + : this(type, new CSBinding[] { new CSBinding(name, value) }) + { + } + + public CSType Type { get; private set; } + public CommaListElementCollection Bindings { get; private set; } + + + public static CSLine VarLine(CSType type, CSIdentifier name, ICSExpression value = null) + { + return new CSLine(new CSVariableDeclaration(type, name, value)); + } + + public static CSLine VarLine(CSType type, string name, ICSExpression value = null) + { + return new CSLine(new CSVariableDeclaration(type, name, value)); + } + + public static CSLine VarLine(string name, ICSExpression value) + { + return new CSLine(new CSVariableDeclaration(CSSimpleType.Var, name, value)); + } + + public static CSLine VarLine(CSIdentifier name, ICSExpression value) + { + return new CSLine(new CSVariableDeclaration(CSSimpleType.Var, name, value)); + } + } + + public class CSFieldDeclaration : CSVariableDeclaration + { + public CSFieldDeclaration(CSType type, IEnumerable bindings, CSVisibility vis = CSVisibility.None, bool isStatic = false, bool isReadonly = false, bool isUnsafe = false) + : base(type, bindings) + { + Visibilty = vis; + IsStatic = isStatic; + IsUnsafe = isUnsafe; + if (isReadonly) + { + this.Insert(0, new SimpleElement("readonly")); + this.Insert(1, SimpleElement.Spacer); + } + if (IsUnsafe) + { + this.Insert(0, new SimpleElement("unsafe")); + this.Insert(1, SimpleElement.Spacer); + } + if (isStatic) + { + this.Insert(0, new SimpleElement("static")); + this.Insert(1, SimpleElement.Spacer); + } + if (vis != CSVisibility.None) + { + this.Insert(0, new SimpleElement(CSMethod.VisibilityToString(vis))); + this.Insert(1, SimpleElement.Spacer); + } + } + + public CSFieldDeclaration(CSType type, string name, ICSExpression value = null, CSVisibility vis = CSVisibility.None, bool isStatic = false, bool isReadonly = false, bool isUnsafe = false) + : this(type, new CSIdentifier(name), value, vis, isStatic, isReadonly, isUnsafe) + { + } + + public CSFieldDeclaration(CSType type, CSIdentifier name, ICSExpression value = null, CSVisibility vis = CSVisibility.None, bool isStatic = false, bool isReadOnly = false, bool isUnsafe = false) + : this(type, new CSBinding[] { new CSBinding(name, value) }, vis, isStatic, isReadOnly, isUnsafe) + { + } + + + public CSVisibility Visibilty { get; private set; } + public bool IsStatic { get; private set; } + public bool IsUnsafe { get; private set; } + + public static CSLine FieldLine(CSType type, CSIdentifier name, ICSExpression value = null, CSVisibility vis = CSVisibility.None, bool isStatic = false) + { + return new CSLine(new CSFieldDeclaration(type, name, value, vis, isStatic)); + } + + public static CSLine FieldLine(CSType type, string name, ICSExpression value = null, CSVisibility vis = CSVisibility.None, bool isStatic = false) + { + return new CSLine(new CSFieldDeclaration(type, name, value, vis, isStatic)); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFile.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFile.cs new file mode 100644 index 000000000000..149e47ca780a --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFile.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSFile : ICodeElementSet + { + public CSFile(CSUsingPackages use, IEnumerable ns) + { + Using = use ?? new CSUsingPackages(); + ns = ns ?? new CSNamespace[0]; + Namespaces = new CSNamespaceBlock(ns); + } + + public static CSFile Create(CSUsingPackages use, params CSNamespace[] ns) + { + return new CSFile(use, ns); + } + + public CSUsingPackages Using { get; private set; } + public CSNamespaceBlock Namespaces { get; private set; } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public object BeginWrite(ICodeWriter writer) + { + OnBegin(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBegin(WriteEventArgs args) + { + Begin(this, args); + } + + public void Write(ICodeWriter writer, object o) + { + } + + public void EndWrite(ICodeWriter writer, object o) + { + OnEnd(new WriteEventArgs(writer)); + } + + protected virtual void OnEnd(WriteEventArgs args) + { + End(this, args); + } + + #endregion + + #region ICodeElemSet implementation + + public System.Collections.Generic.IEnumerable Elements + { + get + { + yield return Using; + yield return Namespaces; + } + } + + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFileBasic.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFileBasic.cs new file mode 100644 index 000000000000..26d618a55575 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFileBasic.cs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSFileBasic : ICodeElementSet + { + string nameSpace; + + public CSFileBasic(string nameSpace) + { + ArgumentNullException.ThrowIfNull(nameSpace, nameof(nameSpace)); + this.nameSpace = nameSpace; + Using = new CSUsingPackages(); + Classes = new CSClasses(); + } + + #region ICodeElem implementation + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public CSClasses Classes { get; private set; } + public CSUsingPackages Using { get; private set; } + + public object BeginWrite(ICodeWriter writer) + { + return null; + } + + public void Write(ICodeWriter writer, object o) + { + } + + public void EndWrite(ICodeWriter writer, object o) + { + } + + protected virtual void OnBegin(WriteEventArgs e) + { + Begin(this, e); + } + + protected virtual void OnEnd(WriteEventArgs e) + { + End(this, e); + } + + #endregion + + #region ICodeElemSet implementation + + public System.Collections.Generic.IEnumerable Elements + { + get + { + yield return Using; + CSNamespace ns = new CSNamespace(nameSpace); + ns.Block.AddRange(Classes); + yield return ns; + } + } + + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFixed.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFixed.cs new file mode 100644 index 000000000000..2f29dbc29399 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFixed.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSFixedCodeBlock : CSCodeBlock, ICSStatement + { + public CSFixedCodeBlock(CSType type, CSIdentifier ident, CSBaseExpression expr, IEnumerable body) + : base(body) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(ident, nameof(ident)); + ArgumentNullException.ThrowIfNull(expr, nameof(expr)); + Type = type; + Identifier = ident; + Expr = expr; + } + + public override void Write(ICodeWriter writer, object o) + { + writer.BeginNewLine(true); + writer.Write("fixed (", true); + Type.Write(writer, o); + writer.Write(' ', false); + Identifier.Write(writer, o); + writer.Write(" = ", true); + Expr.Write(writer, o); + writer.Write(") ", true); + base.Write(writer, o); + } + + public CSType Type { get; private set; } + public CSIdentifier Identifier { get; private set; } + public CSBaseExpression Expr { get; private set; } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSForEach.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSForEach.cs new file mode 100644 index 000000000000..f850cff6d2df --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSForEach.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +namespace SyntaxDynamo.CSLang +{ + public class CSForEach : CodeElementCollection, ICSStatement + { + + class ForElement : DelegatedSimpleElement, ICSStatement + { + public ForElement(CSType type, CSIdentifier ident, CSBaseExpression expr) + : base() + { + Type = type; + Ident = ident; + Expr = expr; + } + + public CSType Type { get; private set; } + public CSIdentifier Ident { get; private set; } + public CSBaseExpression Expr { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.BeginNewLine(true); + writer.Write("foreach (", false); + if (Type != null) + { + Type.WriteAll(writer); + } + else + { + writer.Write("var", false); + } + SimpleElement.Spacer.WriteAll(writer); + Ident.WriteAll(writer); + writer.Write(" in ", true); + Expr.WriteAll(writer); + writer.Write(")", false); + writer.EndLine(); + } + } + + + public CSForEach(CSType type, CSIdentifier ident, CSBaseExpression expr, CSCodeBlock body) + { + ArgumentNullException.ThrowIfNull(ident, nameof(ident)); + ArgumentNullException.ThrowIfNull(expr, nameof(expr)); + Type = type; + Ident = ident; + Expr = expr; + Body = body ?? new CSCodeBlock(); + Add(new ForElement(type, ident, expr)); + Add(Body); + } + + public CSForEach(CSType type, string ident, CSBaseExpression expr, CSCodeBlock body) + : this(type, new CSIdentifier(ident), expr, body) + { + } + + public CSType Type { get; private set; } + public CSIdentifier Ident { get; private set; } + public CSBaseExpression Expr { get; private set; } + public CSCodeBlock Body { get; private set; } + } +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFunctionCall.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFunctionCall.cs new file mode 100644 index 000000000000..c69531c1835c --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSFunctionCall.cs @@ -0,0 +1,137 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSFunctionCall : CSBaseExpression, ICSLineable + { + public CSFunctionCall(CSIdentifier ident, CommaListElementCollection paramList, bool isConstructor = false) + { + ArgumentNullException.ThrowIfNull(ident, nameof(ident)); + ArgumentNullException.ThrowIfNull(paramList, nameof(paramList)); + Name = ident; + Parameters = paramList; + IsConstructor = isConstructor; + } + + public CSFunctionCall(string identifier, bool isConstructor, params CSBaseExpression[] parameters) + : this(new CSIdentifier(identifier), new CommaListElementCollection(parameters), isConstructor) + { + } + + public static CSFunctionCall Function(string identifier, params CSBaseExpression[] parameters) + { + return new CSFunctionCall(identifier, false, parameters); + } + public static CSLine FunctionLine(string identifier, params CSBaseExpression[] parameters) => new CSLine(Function(identifier, parameters)); + + public static CSFunctionCall Ctor(string identifier, params CSBaseExpression[] parameters) + { + return new CSFunctionCall(identifier, true, parameters); + } + public static CSLine CtorLine(string identifier, params CSBaseExpression[] parameters) => new CSLine(Ctor(identifier, parameters)); + + public static CSLine ConsoleWriteLine(params CSBaseExpression[] parameters) => FunctionLine("Console.WriteLine", parameters); + + protected override void LLWrite(ICodeWriter writer, object o) + { + if (IsConstructor) + writer.Write("new ", false); + Name.WriteAll(writer); + writer.Write("(", false); + Parameters.WriteAll(writer); + writer.Write(")", false); + } + + public bool IsConstructor { get; private set; } + public CSIdentifier Name { get; private set; } + public CommaListElementCollection Parameters { get; private set; } + + public static CSLine FunctionCallLine(CSIdentifier identifier, params CSBaseExpression[] parameters) + { + return FunctionCallLine(identifier, false, parameters); + } + + public static CSLine FunctionCallLine(CSIdentifier identifier, bool isConstructor, params CSBaseExpression[] parameters) + { + return new CSLine(new CSFunctionCall(identifier, + new CommaListElementCollection(parameters), isConstructor)); + } + + public static CSLine FunctionCallLine(string identifier, params CSBaseExpression[] parameters) + { + return FunctionCallLine(identifier, false, parameters); + } + + public static CSLine FunctionCallLine(string identifier, bool isConstructor, params CSBaseExpression[] parameters) + { + ArgumentNullException.ThrowIfNull(identifier, nameof(identifier)); + return new CSLine(new CSFunctionCall(new CSIdentifier(identifier), + new CommaListElementCollection(parameters), isConstructor)); + } + + static CSIdentifier iNameOf = new CSIdentifier("nameof"); + + public static CSFunctionCall Nameof(CSIdentifier id) + { + return FooOf(iNameOf, id); + } + + public static CSFunctionCall Nameof(string name) + { + return Nameof(new CSIdentifier(name)); + } + + static CSIdentifier iTypeof = new CSIdentifier("typeof"); + + public static CSFunctionCall Typeof(Type t) + { + return Typeof(t.Name); + } + + public static CSFunctionCall Typeof(string t) + { + return FooOf(iTypeof, new CSIdentifier(t)); + } + + public static CSFunctionCall Typeof(CSSimpleType t) + { + return Typeof(t.Name); + } + + static CSIdentifier iSizeof = new CSIdentifier("sizeof"); + + public static CSFunctionCall Sizeof(CSBaseExpression expr) + { + return FooOf(iSizeof, expr); + } + + static CSIdentifier iDefault = new CSIdentifier("default"); + + public static CSFunctionCall Default(Type t) + { + return Default(t.Name); + } + + public static CSFunctionCall Default(string t) + { + return FooOf(iDefault, new CSIdentifier(t)); + } + + public static CSFunctionCall Default(CSSimpleType t) + { + return Default(t.Name); + } + + static CSFunctionCall FooOf(CSIdentifier foo, CSBaseExpression parameter) + { + CommaListElementCollection parms = new CommaListElementCollection(); + parms.Add(parameter); + return new CSFunctionCall(foo, parms, false); + } + } + +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSGenericConstraint.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSGenericConstraint.cs new file mode 100644 index 000000000000..606539126221 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSGenericConstraint.cs @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSGenericConstraint : DelegatedSimpleElement + { + public CSGenericConstraint(CSIdentifier name, CSIdentifier isA) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + ArgumentNullException.ThrowIfNull(isA, nameof(isA)); + Name = name; + IsA = new CommaListElementCollection(); + IsA.Add(isA); + } + + public CSGenericConstraint(CSIdentifier name, IEnumerable multiIs) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Name = name; + IsA = new CommaListElementCollection(); + if (multiIs != null) + IsA.AddRange(multiIs); + } + + public CSIdentifier Name { get; private set; } + public CommaListElementCollection IsA { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write("where ", true); + Name.Write(writer, o); + writer.Write(" : ", true); + IsA.WriteAll(writer); + } + } + + public class CSGenericConstraintCollection : List, ICodeElementSet + { + public IEnumerable Elements + { + get + { + bool first = true; + foreach (CSGenericConstraint tc in this) + { + if (!first) + { + yield return new LineBreak(); + } + first = false; + yield return tc; + } + } + } + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public virtual object BeginWrite(ICodeWriter writer) + { + OnBeginWrite(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBeginWrite(WriteEventArgs args) + { + Begin(this, args); + } + + public virtual void Write(ICodeWriter writer, object o) + { + } + + public virtual void EndWrite(ICodeWriter writer, object o) + { + OnEndWrite(new WriteEventArgs(writer)); + } + + protected virtual void OnEndWrite(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + } + +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSGenericTypeDeclaration.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSGenericTypeDeclaration.cs new file mode 100644 index 000000000000..cf5db8e79a68 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSGenericTypeDeclaration.cs @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSGenericTypeDeclaration + { + public CSGenericTypeDeclaration(CSIdentifier name) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Name = name; + } + + public CSIdentifier Name { get; private set; } + } + + public class CSGenericTypeDeclarationCollection : List, ICodeElementSet + { + public CSGenericTypeDeclarationCollection() + : base() + { + } + + public IEnumerable Elements + { + get + { + if (this.Count > 0) + { + yield return new SimpleElement("<"); + bool first = true; + foreach (CSGenericTypeDeclaration decl in this) + { + if (!first) + { + yield return new SimpleElement(",", true); + yield return SimpleElement.Spacer; + } + else + { + first = false; + } + yield return decl.Name; + } + yield return new SimpleElement(">"); + } + } + } + + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public virtual object BeginWrite(ICodeWriter writer) + { + OnBeginWrite(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBeginWrite(WriteEventArgs args) + { + Begin(this, args); + } + + public virtual void Write(ICodeWriter writer, object o) + { + } + + public virtual void EndWrite(ICodeWriter writer, object o) + { + OnEndWrite(new WriteEventArgs(writer)); + } + + protected virtual void OnEndWrite(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + } +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIdentifier.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIdentifier.cs new file mode 100644 index 000000000000..4fb13707c02c --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIdentifier.cs @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSIdentifier : CSBaseExpression + { + public CSIdentifier(string name) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Name = name; + } + + public static explicit operator CSIdentifier(string name) + { + return new CSIdentifier(name); + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write(Name, false); + } + + public string Name { get; private set; } + + public override string ToString() + { + return Name; + } + + public static CSIdentifier Create(string name) => new CSIdentifier(name); + + static CSIdentifier thisID = new CSIdentifier("this"); + public static CSIdentifier This { get { return thisID; } } + static CSIdentifier baseID = new CSIdentifier("base"); + public static CSIdentifier Base { get { return baseID; } } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIfElse.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIfElse.cs new file mode 100644 index 000000000000..e0a6a1db9c7a --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIfElse.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSIfElse : CodeElementCollection, ICSStatement + { + class CSIfElement : DelegatedSimpleElement, ICSStatement + { + public CSIfElement(CSBaseExpression condition) + : base() + { + Condition = condition; + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.BeginNewLine(true); + writer.Write("if (", false); + Condition.WriteAll(writer); + writer.Write(")", false); + writer.EndLine(); + } + + public CSBaseExpression Condition { get; private set; } + } + + public CSIfElse(CSBaseExpression condition, CSCodeBlock ifClause, CSCodeBlock elseClause = null) + : base() + { + ArgumentNullException.ThrowIfNull(condition, nameof(condition)); + ArgumentNullException.ThrowIfNull(ifClause, nameof(ifClause)); + Condition = new CSIfElement(condition); + IfClause = ifClause; + ElseClause = elseClause; + + Add(Condition); + Add(IfClause); + if (ElseClause != null && ElseClause.Count > 0) + { + Add(new SimpleLineElement("else", false, true, false)); + Add(ElseClause); + } + } + + public CSIfElse(CSBaseExpression expr, IEnumerable ifClause, IEnumerable elseClause) + : this(expr, new CSCodeBlock(ifClause), + elseClause != null ? new CSCodeBlock(elseClause) : null) + + { + + } + + public DelegatedSimpleElement Condition { get; private set; } + public CSCodeBlock IfClause { get; private set; } + public CSCodeBlock ElseClause { get; private set; } + + + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIndexExpression.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIndexExpression.cs new file mode 100644 index 000000000000..62b0df4a4edf --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSIndexExpression.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSIndexExpression : CSBaseExpression + { + public CSIndexExpression(CSBaseExpression aggregate, CommaListElementCollection paramList, bool addParensAroundAggregate) + { + ArgumentNullException.ThrowIfNull(aggregate, nameof(aggregate)); + ArgumentNullException.ThrowIfNull(paramList, nameof(paramList)); + AddParensAroundAggregate = addParensAroundAggregate; + Aggregate = aggregate; + Parameters = paramList; + } + + public CSIndexExpression(string identifier, bool addParensAroundAggregate, params CSBaseExpression[] parameters) + : this(new CSIdentifier(identifier), new CommaListElementCollection(parameters), addParensAroundAggregate) + { + } + + public CSIndexExpression(CSBaseExpression aggregate, bool addParensAroundAggregate, params CSBaseExpression[] parameters) + : this(aggregate, new CommaListElementCollection(parameters), addParensAroundAggregate) + { + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + if (AddParensAroundAggregate) + writer.Write('(', false); + Aggregate.WriteAll(writer); + if (AddParensAroundAggregate) + writer.Write(')', false); + writer.Write("[", false); + Parameters.WriteAll(writer); + writer.Write("]", false); + } + + public bool AddParensAroundAggregate { get; private set; } + public CSBaseExpression Aggregate { get; private set; } + public CommaListElementCollection Parameters { get; private set; } + + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInheritance.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInheritance.cs new file mode 100644 index 000000000000..58d3a9b3547d --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInheritance.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; + +namespace SyntaxDynamo.CSLang +{ + public class CSInheritance : CommaListElementCollection + { + public CSInheritance(IEnumerable identifiers) + { + if (identifiers != null) + AddRange(identifiers); + } + + public CSInheritance(params string[] identifiers) + : this(identifiers.Select(str => new CSIdentifier(str))) + { + } + + public void Add(Type t) + { + ArgumentNullException.ThrowIfNull(t, "t"); + Add(new CSIdentifier(t.Name)); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInitializer.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInitializer.cs new file mode 100644 index 000000000000..388dcd9dd6ad --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInitializer.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSInitializer : CSBaseExpression + { + public CSInitializer(IEnumerable parameters, bool appendNewlineAfterEach) + { + Parameters = new CommaListElementCollection("", "", parameters, appendNewlineAfterEach); + } + + public CommaListElementCollection Parameters { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write("{ ", false); + Parameters.WriteAll(writer); + writer.Write(" }", false); + } + } + + public class CSInitializedType : CSBaseExpression + { + public CSInitializedType(CSFunctionCall call, CSInitializer initializer) + { + ArgumentNullException.ThrowIfNull(call, nameof(call)); + ArgumentNullException.ThrowIfNull(initializer, nameof(initializer)); + Call = call; + Initializer = initializer; + } + + public CSInitializedType(CSFunctionCall call, IEnumerable parameters, bool appendNewlineAfterEach) + : this(call, new CSInitializer(parameters, appendNewlineAfterEach)) + { + } + + public CSFunctionCall Call { get; private set; } + public CSInitializer Initializer { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + Call.WriteAll(writer); + SimpleElement.Spacer.WriteAll(writer); + Initializer.WriteAll(writer); + } + } +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInject.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInject.cs new file mode 100644 index 000000000000..a522a92b4e8f --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInject.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SyntaxDynamo.CSLang +{ + // CSInject is a way to more formalize the notion of code that is just plain easier to + // inject as raw text. It's not strictly necessary, but when you see a CSInject, it will make + // it clear that you're doing something not quite on the up and up. + public class CSInject : CSIdentifier + { + public CSInject(string name) + : base(name) + { + } + + public static explicit operator CSInject(string name) + { + return new CSInject(name); + } + } +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInterface.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInterface.cs new file mode 100644 index 000000000000..26eec748786b --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSInterface.cs @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SyntaxDynamo.CSLang +{ + public class CSInterface : ICodeElementSet, ICSTopLevelDeclaration + { + public CSInterface(CSVisibility vis, CSIdentifier name, + IEnumerable methods = null) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + Visibility = vis; + Name = name; + Inheritance = new CSInheritance(); + Methods = new List(); + Properties = new List(); + GenericParams = new CSGenericTypeDeclarationCollection(); + GenericConstraints = new CSGenericConstraintCollection(); + if (methods != null) + Methods.AddRange(methods); + } + + public CSInterface(CSVisibility vis, string name, IEnumerable methods = null) + : this(vis, new CSIdentifier(name), methods) + { + } + + + public CSType ToCSType(IEnumerable genericReplacements) + { + var replacements = genericReplacements.ToList(); + if (replacements.Count < GenericParams.Count) + { + replacements.AddRange(GenericParams.Skip(replacements.Count).Select(gen => new CSSimpleType(gen.Name.Name))); + } + return new CSSimpleType(Name.Name, false, replacements.ToArray()); + } + + public CSType ToCSType() + { + return ToCSType(GenericParams.Select(gen => new CSSimpleType(gen.Name.Name))); + } + + public CSVisibility Visibility { get; private set; } + public CSIdentifier Name { get; private set; } + public CSInheritance Inheritance { get; private set; } + public List Methods { get; private set; } + public List Properties { get; private set; } + public CSGenericTypeDeclarationCollection GenericParams { get; private set; } + public CSGenericConstraintCollection GenericConstraints { get; private set; } + + #region ICodeElem implementation + public event EventHandler Begin = (s, e) => { }; + + public event EventHandler End = (s, e) => { }; + + public virtual object BeginWrite(ICodeWriter writer) + { + OnBeginWrite(new WriteEventArgs(writer)); + return null; + } + + protected virtual void OnBeginWrite(WriteEventArgs args) + { + Begin(this, args); + } + + public virtual void Write(ICodeWriter writer, object o) + { + } + + public virtual void EndWrite(ICodeWriter writer, object o) + { + OnEndWrite(new WriteEventArgs(writer)); + } + + protected virtual void OnEndWrite(WriteEventArgs args) + { + End.FireInReverse(this, args); + } + + #endregion + + #region ICodeElemSet implementation + + public IEnumerable Elements + { + get + { + var decl = new LineCodeElementCollection(true, false, true); + if (Visibility != CSVisibility.None) + decl.Add(new SimpleElement(CSMethod.VisibilityToString(Visibility) + " ")); + decl.Add(new CSIdentifier("interface ")); + decl.Add(Name); + + decl.Add(GenericParams); + if (Inheritance.Count > 0) + { + decl.Add(new SimpleElement(" : ", true)); + decl.Add(Inheritance); + } + if (GenericConstraints.Count > 0) + { + decl.Add(SimpleElement.Spacer); + decl.Add(GenericConstraints); + } + yield return decl; + + var contents = new DecoratedCodeElementCollection("{", "}", + true, true, true); + + contents.AddRange(Methods); + contents.AddRange(Properties); + + yield return contents; + + } + } + + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSLambda.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSLambda.cs new file mode 100644 index 000000000000..26d3ede9f7d4 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSLambda.cs @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Linq; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSLambda : CSBaseExpression + { + public CSLambda(CSParameterList parameters, ICSExpression value) + { + ArgumentNullException.ThrowIfNull(value, nameof(value)); + Parameters = parameters ?? new CSParameterList(); + Value = value; + Body = null; + } + + public CSLambda(CSParameterList parameters, CSCodeBlock body) + { + body = body ?? new CSCodeBlock(); + Parameters = parameters ?? new CSParameterList(); + Value = null; + Body = body; + } + + public CSLambda(ICSExpression value, params string[] parameters) + : this(new CSParameterList(parameters.Select(p => new CSParameter(CSSimpleType.Void, new CSIdentifier(p)))), value) + { + } + + public CSLambda(CSCodeBlock body, params string[] parameters) + : this(new CSParameterList(parameters.Select(p => new CSParameter(CSSimpleType.Void, new CSIdentifier(p)))), body) + { + } + + + public CSParameterList Parameters { get; private set; } + public ICSExpression Value { get; private set; } + public CSCodeBlock Body { get; private set; } + + #region implemented abstract members of DelegatedSimpleElem + + protected override void LLWrite(ICodeWriter writer, object o) + { + // hack - Parameters really want types. If you set them to void, we'll consider them to be + // typeless. + bool allVoid = Parameters.All(p => p.CSType == CSSimpleType.Void); + + writer.Write('(', true); + if (allVoid) + { + bool didFirst = false; + foreach (CSParameter p in Parameters) + { + if (didFirst) + { + writer.Write(", ", true); + } + p.Name.WriteAll(writer); + didFirst = true; + } + } + else + { + Parameters.WriteAll(writer); + } + writer.Write(") => ", true); + if (Value != null) + { + Value.WriteAll(writer); + } + else + { + Body.WriteAll(writer); + } + } + + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSLine.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSLine.cs new file mode 100644 index 000000000000..283814feffb6 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSLine.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSLine : DelegatedSimpleElement, ICSStatement + { + public CSLine(ICodeElement contents, bool addSemicolon = true) + { + ArgumentNullException.ThrowIfNull(contents, nameof(contents)); + Contents = contents; + if (!(contents is ICSLineable) && addSemicolon) + throw new ArgumentException("contents must be ILineable", nameof(contents)); + AddSemicolon = addSemicolon; + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.BeginNewLine(true); + Contents.WriteAll(writer); + if (AddSemicolon) + writer.Write(';', false); + writer.EndLine(); + } + + public ICodeElement Contents { get; private set; } + public bool AddSemicolon { get; set; } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSMethod.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSMethod.cs new file mode 100644 index 000000000000..95c5731075ee --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSMethod.cs @@ -0,0 +1,251 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSMethod : CodeElementCollection + { + public CSMethod(CSVisibility vis, CSMethodKind kind, CSType type, CSIdentifier name, CSParameterList parms, CSCodeBlock body) + : this(vis, kind, type, name, parms, null, false, body) + { + + } + public CSMethod(CSVisibility vis, CSMethodKind kind, CSType type, CSIdentifier name, + CSParameterList parms, CSBaseExpression[] baseOrThisCallParms, bool callsBase, CSCodeBlock body, bool isSealed = false, + bool isAsync = false) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + ArgumentNullException.ThrowIfNull(parms, nameof(parms)); + GenericParameters = new CSGenericTypeDeclarationCollection(); + GenericConstraints = new CSGenericConstraintCollection(); + Visibility = vis; + Kind = kind; + Type = type; // no throw on null - could be constructor + Name = name; + Parameters = parms; + CallsBase = callsBase; + BaseOrThisCallParameters = baseOrThisCallParms; + + Body = body; // can be null + IsSealed = isSealed; + IsAsync = isAsync; + + LineCodeElementCollection lc = new LineCodeElementCollection(new ICodeElement[0], false, true); + if (vis != CSVisibility.None) + { + lc.And(new SimpleElement(VisibilityToString(vis))).And(SimpleElement.Spacer); + } + + if (isSealed) + { + lc.And(new SimpleElement("sealed")).And(SimpleElement.Spacer); + } + + if (isAsync) + { + lc.And(new SimpleElement("async")).And(SimpleElement.Spacer); + } + + lc.And(new SimpleElement(MethodKindToString(kind))).And(SimpleElement.Spacer); + + if (type != null) + { + lc.And(type).And(SimpleElement.Spacer); + } + + lc.And(name).And(GenericParameters).And(new SimpleElement("(")).And(parms).And(new SimpleElement(")")).And(GenericConstraints); + if (body == null) + { + if (!(kind == CSMethodKind.StaticExtern || kind == CSMethodKind.Interface)) + throw new ArgumentException("Method body is only optional when method kind kind is either StaticExtern or Interface", + nameof(body)); + lc.Add(new SimpleElement(";")); + } + Add(lc); + if (BaseOrThisCallParameters != null) + { + Add(new CSFunctionCall(CallsBase ? ": base" : ": this", false, BaseOrThisCallParameters)); + } + if (body != null) + Add(body); + } + + public CSVisibility Visibility { get; private set; } + public CSMethodKind Kind { get; private set; } + public CSType Type { get; private set; } + public CSIdentifier Name { get; private set; } + public CSParameterList Parameters { get; private set; } + public bool CallsBase { get; private set; } + public CSBaseExpression[] BaseOrThisCallParameters { get; private set; } + public CSCodeBlock Body { get; private set; } + public CSGenericTypeDeclarationCollection GenericParameters { get; private set; } + public CSGenericConstraintCollection GenericConstraints { get; private set; } + public bool IsSealed { get; private set; } + public bool IsAsync { get; private set; } + + public CSMethod AsSealed() + { + var sealedMethod = new CSMethod(Visibility, Kind, Type, Name, Parameters, BaseOrThisCallParameters, CallsBase, Body, true); + return CopyGenerics(this, sealedMethod); + } + + public CSMethod AsOverride() + { + var overrideMethod = new CSMethod(Visibility, CSMethodKind.Override, Type, Name, Parameters, BaseOrThisCallParameters, CallsBase, Body, IsSealed); + return CopyGenerics(this, overrideMethod); + } + + public CSMethod AsPrivate() + { + var privateMethod = new CSMethod(CSVisibility.None, Kind, Type, Name, Parameters, BaseOrThisCallParameters, CallsBase, Body, IsSealed); + return CopyGenerics(this, privateMethod); + } + + public static CSMethod CopyGenerics(CSMethod from, CSMethod to) + { + to.GenericParameters.AddRange(from.GenericParameters); + to.GenericConstraints.AddRange(from.GenericConstraints); + return to; + } + + public static CSMethod RemoveGenerics(CSMethod from) + { + var newMethod = new CSMethod(from.Visibility, from.Kind, from.Type, from.Name, from.Parameters, from.Body); + return newMethod; + } + + public static string VisibilityToString(CSVisibility visibility) + { + switch (visibility) + { + case CSVisibility.None: + return ""; + case CSVisibility.Internal: + return "internal"; + case CSVisibility.Private: + return "private"; + case CSVisibility.Public: + return "public"; + case CSVisibility.Protected: + return "protected"; + default: + throw new ArgumentOutOfRangeException("vis"); + } + } + + public static string MethodKindToString(CSMethodKind kind) + { + switch (kind) + { + case CSMethodKind.None: + case CSMethodKind.Interface: + return ""; + case CSMethodKind.Extern: + return "extern"; + case CSMethodKind.New: + return "new"; + case CSMethodKind.Override: + return "override"; + case CSMethodKind.Static: + return "static"; + case CSMethodKind.StaticExtern: + return "static extern"; + case CSMethodKind.StaticNew: + return "static new"; + case CSMethodKind.Virtual: + return "virtual"; + case CSMethodKind.Abstract: + return "abstract"; + case CSMethodKind.Unsafe: + return "unsafe"; + case CSMethodKind.StaticUnsafe: + return "static unsafe"; + default: + throw new ArgumentOutOfRangeException(nameof(kind)); + } + } + + public static CSMethod PublicMethod(CSType type, string name, CSParameterList parms, CSCodeBlock body) + { + ArgumentNullException.ThrowIfNull(body, nameof(body)); + return new CSMethod(CSVisibility.Public, CSMethodKind.None, type, new CSIdentifier(name), parms, body); + } + + public static CSMethod PublicMethod(CSMethodKind kind, CSType type, string name, CSParameterList parms, CSCodeBlock body) + { + ArgumentNullException.ThrowIfNull(body, nameof(body)); + return new CSMethod(CSVisibility.Public, kind, type, new CSIdentifier(name), parms, body); + } + + public static CSMethod PublicConstructor(string name, CSParameterList parms, CSCodeBlock body) + { + ArgumentNullException.ThrowIfNull(body, nameof(body)); + return new CSMethod(CSVisibility.Public, CSMethodKind.None, null, new CSIdentifier(name), parms, body); + } + + public static CSMethod PublicConstructor(string name, CSParameterList parms, CSCodeBlock body, params CSBaseExpression[] baseParams) + { + ArgumentNullException.ThrowIfNull(body, nameof(body)); + return new CSMethod(CSVisibility.Public, CSMethodKind.None, null, new CSIdentifier(name), parms, + baseParams, true, body); + } + + public static CSMethod PrivateConstructor(string name, CSParameterList parms, CSCodeBlock body) + { + ArgumentNullException.ThrowIfNull(body, nameof(body)); + return new CSMethod(CSVisibility.None, CSMethodKind.None, null, new CSIdentifier(name), parms, body); + } + + public static CSMethod PrivateConstructor(string name, CSParameterList parms, CSCodeBlock body, params CSBaseExpression[] baseParams) + { + ArgumentNullException.ThrowIfNull(body, nameof(body)); + return new CSMethod(CSVisibility.None, CSMethodKind.None, null, new CSIdentifier(name), parms, + baseParams, true, body); + } + + public static CSMethod PInvoke(CSVisibility vis, CSType type, string name, string dllName, string externName, CSParameterList parms) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + CSMethod method = new CSMethod(vis, CSMethodKind.StaticExtern, type, + new CSIdentifier(name), parms, null); + + CSAttribute.DllImport(dllName, externName).AttachBefore(method); + + return method; + } + + public static CSMethod PInvoke(CSVisibility vis, CSType type, string name, CSBaseExpression dllName, string externName, CSParameterList parms) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + CSMethod method = new CSMethod(vis, CSMethodKind.StaticExtern, type, + new CSIdentifier(name), parms, null); + + CSAttribute.DllImport(dllName, externName).AttachBefore(method); + + return method; + } + + public static CSMethod PublicPInvoke(CSType type, string name, string dllName, string externName, CSParameterList parms) + { + return PInvoke(CSVisibility.Public, type, name, dllName, externName, parms); + } + + public static CSMethod PrivatePInvoke(CSType type, string name, string dllName, string externName, CSParameterList parms) + { + return PInvoke(CSVisibility.None, type, name, dllName, externName, parms); + } + + public static CSMethod InternalPInvoke(CSType type, string name, string dllName, string externName, CSParameterList parms) + { + return PInvoke(CSVisibility.Internal, type, name, dllName, externName, parms); + } + + + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSNamespace.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSNamespace.cs new file mode 100644 index 000000000000..b967392f3d3f --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSNamespace.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; +using System.Linq; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public class CSNamespace : LabeledCodeElementCollection + { + public CSNamespace() + : base(new SimpleLineElement(string.Empty, false, false, false), + new DecoratedCodeElementCollection(string.Empty, string.Empty, false, false, false)) + { + } + + public CSNamespace(string nameSpace) + : base(new SimpleLineElement(string.Format("namespace {0}", nameSpace), + false, true, false), + new DecoratedCodeElementCollection("{", "}", true, true, true)) + { + } + + } + + public class CSNamespaceBlock : CodeElementCollection + { + public CSNamespaceBlock(params string[] nameSpaces) + : base() + { + this.AddRange(nameSpaces.Select(s => new CSNamespace(s))); + } + + public CSNamespaceBlock(IEnumerable nameSpaces) + : base() + { + this.AddRange(nameSpaces); + } + + public CSNamespaceBlock And(string s) + { + return And(new CSNamespace(s)); + } + + public CSNamespaceBlock And(CSNamespace ns) + { + ArgumentNullException.ThrowIfNull(ns, nameof(ns)); + Add(ns); + return this; + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSParameter.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSParameter.cs new file mode 100644 index 000000000000..bfd4c5759b33 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSParameter.cs @@ -0,0 +1,120 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using SyntaxDynamo; + + +namespace SyntaxDynamo.CSLang +{ + public class CSParameter : DelegatedSimpleElement + { + public CSParameter(CSType type, CSIdentifier name, + CSParameterKind parameterKind = CSParameterKind.None, + CSConstant defaultValue = null) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(name, nameof(name)); + CSType = type; + Name = name; + ParameterKind = parameterKind; + DefaultValue = defaultValue; + } + + public CSParameter(CSType type, string name, + CSParameterKind parameterKind = CSParameterKind.None, + CSConstant defaultValue = null) + : this(type, new CSIdentifier(name), parameterKind, defaultValue) + { + } + + public CSParameter(string type, string name, + CSParameterKind parameterKind = CSParameterKind.None, + CSConstant defaultValue = null) + : this(new CSSimpleType(type), new CSIdentifier(name), parameterKind, defaultValue) + { + } + + + protected override void LLWrite(ICodeWriter writer, object o) + { + if (this.ParameterKind != CSParameterKind.None) + { + writer.Write(ToParameterKindString(this.ParameterKind), false); + writer.Write(' ', false); + } + this.CSType.WriteAll(writer); + writer.Write(' ', true); + Name.WriteAll(writer); + if ((Object)DefaultValue != null) + { + writer.Write(" = ", true); + DefaultValue.WriteAll(writer); + } + } + + static string ToParameterKindString(CSParameterKind parameterKind) + { + switch (parameterKind) + { + case CSParameterKind.None: + return ""; + case CSParameterKind.Out: + return "out"; + case CSParameterKind.Ref: + return "ref"; + case CSParameterKind.This: + return "this"; + case CSParameterKind.Params: + return "params"; + default: + throw new ArgumentOutOfRangeException(nameof(parameterKind), "unexpected parameter kind " + parameterKind.ToString()); + } + } + + public CSType CSType { get; private set; } + public CSIdentifier Name { get; private set; } + public CSConstant DefaultValue { get; private set; } + public CSParameterKind ParameterKind { get; private set; } + } + + public class CSParameterList : CommaListElementCollection + { + public CSParameterList(IEnumerable parameters) + : base() + { + if (parameters != null) + AddRange(parameters); + } + public CSParameterList(params CSParameter[] parameters) + : base() + { + if (parameters != null) + AddRange(parameters); + } + + public CSParameterList() : this((IEnumerable)null) { } + + public CSParameterList(CSParameter parameter) : this(new CSParameter[] { parameter }) { } + + public CSParameterList And(CSParameter parameter) + { + ArgumentNullException.ThrowIfNull(parameter, nameof(parameter)); + Add(parameter); + return this; + } + + public CSParameterList And(string type, string identifier, + CSParameterKind parameterKind = CSParameterKind.None, + CSConstant defaultValue = null) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(identifier, nameof(identifier)); + return And(new CSParameter(new CSSimpleType(type), + new CSIdentifier(identifier), parameterKind, defaultValue)); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSParenthesisExpression.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSParenthesisExpression.cs new file mode 100644 index 000000000000..a5f5acefe050 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSParenthesisExpression.cs @@ -0,0 +1,53 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSParenthesisExpression : CSBaseExpression + { + public CSParenthesisExpression(ICSExpression within) + { + ArgumentNullException.ThrowIfNull(within, nameof(within)); + Within = within; + } + + public ICSExpression Within { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write('(', true); + Within.WriteAll(writer); + writer.Write(')', true); + } + } + + public class CSCastExpression : CSBaseExpression, ICSLineable + { + public CSCastExpression(string type, ICSExpression toCast) + : this(new CSSimpleType(type), toCast) + { + } + + public CSCastExpression(CSType type, ICSExpression toCast) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(toCast, nameof(toCast)); + Type = type; + ToCast = toCast; + } + + public CSType Type { get; private set; } + public ICSExpression ToCast { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write("(", true); + Type.WriteAll(writer); + writer.Write(')', true); + ToCast.WriteAll(writer); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSProperty.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSProperty.cs new file mode 100644 index 000000000000..716c8c95aa7f --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSProperty.cs @@ -0,0 +1,208 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Text; +using System.Collections.Generic; +using System.Linq; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSProperty : CodeElementCollection + { + public CSProperty(CSType type, CSMethodKind kind, CSIdentifier name, + CSVisibility getVis, IEnumerable getter, + CSVisibility setVis, IEnumerable setter) + : this(type, kind, name, + getVis, getter != null ? new CSCodeBlock(getter) : null, + setVis, setter != null ? new CSCodeBlock(setter) : null) + { + } + + + public CSProperty(CSType type, CSMethodKind kind, CSIdentifier name, + CSVisibility getVis, CSCodeBlock getter, + CSVisibility setVis, CSCodeBlock setter) + : this(type, kind, name, getVis, getter, setVis, setter, null) + { + } + + public CSProperty(CSType type, CSMethodKind kind, + CSVisibility getVis, CSCodeBlock getter, + CSVisibility setVis, CSCodeBlock setter, CSParameterList parms) + : this(type, kind, new CSIdentifier("this"), getVis, getter, setVis, setter, + parms) + { + } + + CSProperty(CSType type, CSMethodKind kind, CSIdentifier name, + CSVisibility getVis, CSCodeBlock getter, + CSVisibility setVis, CSCodeBlock setter, CSParameterList parms) + { + ArgumentNullException.ThrowIfNull(type, nameof(type)); + ArgumentNullException.ThrowIfNull(name, nameof(name)); + bool unifiedVis = getVis == setVis; + IndexerParameters = parms; + + LineCodeElementCollection decl = new LineCodeElementCollection(null, false, true); + + GetterVisibility = getVis; + SetterVisibility = setVis; + CSVisibility bestVis = (CSVisibility)Math.Min((int)getVis, (int)setVis); + decl.And(new SimpleElement(CSMethod.VisibilityToString(bestVis))).And(SimpleElement.Spacer); + if (kind != CSMethodKind.None) + decl.And(new SimpleElement(CSMethod.MethodKindToString(kind))).And(SimpleElement.Spacer); + + PropType = type; + Name = name; + + decl.And(type).And(SimpleElement.Spacer) + .And(name); + if (parms != null) + { + decl.And(new SimpleElement("[", true)).And(parms).And(new SimpleElement("]")); + } + Add(decl); + + + CSCodeBlock cb = new CSCodeBlock(null); + + if (getter != null) + { + Getter = getter; + LineCodeElementCollection getLine = MakeEtter(getVis, "get", unifiedVis, getVis > setVis); + cb.Add(getLine); + if (getter.Count() == 0) + { + getLine.Add(new SimpleElement(";")); + } + else + { + cb.Add(getter); + } + } + if (setter != null) + { + Setter = setter; + LineCodeElementCollection setLine = MakeEtter(setVis, "set", unifiedVis, setVis > getVis); + cb.Add(setLine); + if (setter.Count() == 0) + { + setLine.Add(new SimpleElement(";")); + } + else + { + cb.Add(setter); + } + } + + Add(cb); + } + public CSType PropType { get; private set; } + public CSIdentifier Name { get; private set; } + public CSParameterList IndexerParameters { get; private set; } + public CSVisibility GetterVisibility { get; private set; } + public CSVisibility SetterVisibility { get; private set; } + + public CSCodeBlock Getter { get; private set; } + + public CSCodeBlock Setter { get; private set; } + + static LineCodeElementCollection MakeEtter(CSVisibility vis, string getset, + bool unifiedVis, bool moreRestrictiveVis) + { + LineCodeElementCollection getLine = new LineCodeElementCollection(null, false, true); + if (!unifiedVis && vis != CSVisibility.None && moreRestrictiveVis) + getLine.And(new SimpleElement(CSMethod.VisibilityToString(vis))).And(SimpleElement.Spacer); + return getLine.And(new SimpleElement(getset, false)); + } + + public static CSProperty PublicGetSet(CSType type, string name) + { + return new CSProperty(type, CSMethodKind.None, new CSIdentifier(name), + CSVisibility.Public, new CSCodeBlock(), CSVisibility.Public, new CSCodeBlock()); + } + + public static CSProperty PublicGetPrivateSet(CSType type, string name) + { + return new CSProperty(type, CSMethodKind.None, new CSIdentifier(name), + CSVisibility.Public, new CSCodeBlock(), CSVisibility.Private, new CSCodeBlock()); + } + + static CSProperty PublicGetPubPrivSetBacking(CSType type, string name, bool declareField, bool setIsPublic, string backingFieldName = null) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + if (!declareField && backingFieldName == null) + throw new ArgumentException("declareField must be true if there is no supplied field name", nameof(declareField)); + backingFieldName = backingFieldName ?? MassageName(name); + + + CSIdentifier backingIdent = new CSIdentifier(backingFieldName); + LineCodeElementCollection getCode = + new LineCodeElementCollection(new ICodeElement[] { CSReturn.ReturnLine(backingIdent) }, false, true); + LineCodeElementCollection setCode = + new LineCodeElementCollection( + new ICodeElement[] { + CSAssignment.Assign (backingFieldName, new CSIdentifier ("value")) + }, false, true); + CSProperty prop = new CSProperty(type, CSMethodKind.None, new CSIdentifier(name), CSVisibility.Public, + new CSCodeBlock(getCode), + (setIsPublic ? CSVisibility.Public : CSVisibility.Private), new CSCodeBlock(setCode)); + if (declareField) + prop.Insert(0, CSFieldDeclaration.FieldLine(type, backingFieldName)); + return prop; + } + + + public static CSProperty PublicGetSetBacking(CSType type, string name, bool declareField, string backingFieldName = null) + { + return PublicGetPubPrivSetBacking(type, name, true, declareField, backingFieldName); + } + + public static CSProperty PublicGetPrivateSetBacking(CSType type, string name, bool declareField, string backingFieldName = null) + { + return PublicGetPubPrivSetBacking(type, name, false, declareField, backingFieldName); + } + + public static CSProperty PublicGetBacking(CSType type, CSIdentifier name, CSIdentifier backingFieldName, + bool includeBackingFieldDeclaration = false, CSMethodKind methodKind = CSMethodKind.None) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + ArgumentNullException.ThrowIfNull(backingFieldName, nameof(backingFieldName)); + LineCodeElementCollection getCode = + new LineCodeElementCollection( + new ICodeElement[] { + CSReturn.ReturnLine (backingFieldName) + }, false, true); + CSProperty prop = new CSProperty(type, methodKind, name, + CSVisibility.Public, new CSCodeBlock(getCode), + CSVisibility.Public, null); + if (includeBackingFieldDeclaration) + prop.Insert(0, CSFieldDeclaration.FieldLine(type, backingFieldName)); + return prop; + } + + + public static CSProperty PublicGetBacking(CSType type, string name, string backingFieldName, bool includeBackingFieldDeclaration = false) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + ArgumentNullException.ThrowIfNull(backingFieldName, nameof(backingFieldName)); + return PublicGetBacking(type, + new CSIdentifier(name), + new CSIdentifier(backingFieldName), + includeBackingFieldDeclaration); + } + + static string MassageName(string name) + { + StringBuilder sb = new StringBuilder(); + sb.Append("_"); + sb.Append(Char.ToLowerInvariant(name[0])); + if (name.Length > 0) + sb.Append(name.Substring(1)); + return sb.ToString(); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSReturn.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSReturn.cs new file mode 100644 index 000000000000..2bf81720aab2 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSReturn.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SyntaxDynamo.CSLang +{ + public class CSReturn : DelegatedSimpleElement, ICSExpression, ICSLineable + { + public CSReturn(ICSExpression expr) + { + Value = expr; + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write("return ", true); + if (Value != null) + Value.WriteAll(writer); + } + + public ICSExpression Value { get; private set; } + + public static CSLine ReturnLine(ICSExpression expr) + { + return new CSLine(new CSReturn(expr)); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSShortCircuit.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSShortCircuit.cs new file mode 100644 index 000000000000..a5b80fd321d7 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSShortCircuit.cs @@ -0,0 +1,34 @@ +using System; +namespace SyntaxDynamo.CSLang +{ + public class CSShortCircuit : DelegatedSimpleElement, ICSLineable + { + public CSShortCircuit(CSShortCircuitKind kind) + { + Kind = kind; + } + + public CSShortCircuitKind Kind { get; private set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + var keyword = Kind == CSShortCircuitKind.Break ? "break" : "continue"; + writer.Write(keyword, false); + } + + public static CSLine ShortCircuit(CSShortCircuitKind kind) + { + return new CSLine(new CSShortCircuit(kind)); + } + + public static CSLine Continue() + { + return ShortCircuit(CSShortCircuitKind.Continue); + } + + public static CSLine Break() + { + return ShortCircuit(CSShortCircuitKind.Break); + } + } +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSTernary.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSTernary.cs new file mode 100644 index 000000000000..e4c73ddb38e8 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSTernary.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSTernary : CSBaseExpression + { + public CSTernary(CSBaseExpression predicate, CSBaseExpression onTrue, CSBaseExpression onFalse, bool addParentheses) + { + ArgumentNullException.ThrowIfNull(predicate, nameof(predicate)); + ArgumentNullException.ThrowIfNull(onTrue, nameof(onTrue)); + ArgumentNullException.ThrowIfNull(onFalse, nameof(onFalse)); + Predicate = predicate; + OnTrue = onTrue; + OnFalse = onFalse; + AddParentheses = addParentheses; + } + public CSBaseExpression Predicate { get; private set; } + public CSBaseExpression OnTrue { get; private set; } + public CSBaseExpression OnFalse { get; private set; } + public bool AddParentheses { get; set; } + + #region implemented abstract members of DelegatedSimpleElem + + protected override void LLWrite(ICodeWriter writer, object o) + { + if (AddParentheses) + { + writer.Write('(', true); + } + Predicate.WriteAll(writer); + writer.Write(" ? ", true); + OnTrue.WriteAll(writer); + writer.Write(" : ", true); + OnFalse.WriteAll(writer); + if (AddParentheses) + { + writer.Write(')', true); + } + } + + #endregion + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSThrow.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSThrow.cs new file mode 100644 index 000000000000..09d429718032 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSThrow.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSThrow : CSBaseExpression, ICSStatement, ICSLineable + { + public CSThrow(CSBaseExpression expr) + { + ArgumentNullException.ThrowIfNull(expr, nameof(expr)); + Expr = expr; + } + + public CSBaseExpression Expr { get; private set; } + + #region implemented abstract members of DelegatedSimpleElem + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write("throw ", true); + Expr.WriteAll(writer); + } + + #endregion + + public static CSLine ThrowLine(T exType, CommaListElementCollection args) where T : Exception + { + return new CSLine(new CSThrow(new CSFunctionCall(new CSIdentifier(exType.GetType().Name), args, true))); + } + + public static CSLine ThrowLine(T exType, string message) where T : Exception + { + CommaListElementCollection args = new CommaListElementCollection(); + if (message != null) + args.Add(CSConstant.Val(message)); + return ThrowLine(exType, args); + } + + public static CSLine ThrowLine(T exType, CSBaseExpression expr) where T : Exception + { + ArgumentNullException.ThrowIfNull(expr, nameof(expr)); + CommaListElementCollection args = new CommaListElementCollection(); + args.Add(expr); + return ThrowLine(exType, args); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSTryCatch.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSTryCatch.cs new file mode 100644 index 000000000000..1b4329f853d6 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSTryCatch.cs @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +namespace SyntaxDynamo.CSLang +{ + public class CSCatch : DelegatedSimpleElement, ICSStatement + { + public CSCatch(CSType catchType, CSIdentifier name, CSCodeBlock body) + { + CatchType = catchType; + Name = name; + Body = body ?? new CSCodeBlock(); + } + + public CSCatch(string catchType, string name, CSCodeBlock body) + : this(new CSSimpleType(catchType), name != null ? new CSIdentifier(name) : null, body) + { + } + + public CSCatch(Type catchType, string name, CSCodeBlock body) + : this(new CSSimpleType(catchType), name != null ? new CSIdentifier(name) : null, body) + { + } + + public CSCatch(CSCodeBlock body) + : this((CSType)null, null, body) + { + } + + public CSType CatchType { get; private set; } + public CSIdentifier Name { get; private set; } + public CSCodeBlock Body { get; private set; } + protected override void LLWrite(ICodeWriter writer, object o) + { + + writer.BeginNewLine(true); + writer.Write("catch ", false); + if ((object)CatchType != null) + { + writer.Write("(", false); + CatchType.WriteAll(writer); + if ((object)Name != null) + { + SimpleElement.Spacer.WriteAll(writer); + Name.WriteAll(writer); + } + writer.Write(")", false); + } + writer.EndLine(); + Body.WriteAll(writer); + writer.EndLine(); + } + } + + public class CSTryCatch : CodeElementCollection, ICSStatement + { + public CSTryCatch(CSCodeBlock tryBlock, params CSCatch[] catchBlocks) + { + TryBlock = tryBlock ?? new CSCodeBlock(); + CatchBlocks = new CodeElementCollection(); + CatchBlocks.AddRange(catchBlocks); + + Add(new SimpleElement("try ", true)); + Add(TryBlock); + Add(CatchBlocks); + } + + public CSTryCatch(CSCodeBlock tryBlock, Type catchType, string name, CSCodeBlock catchBlock) + : this(tryBlock, new CSCatch(catchType, name, catchBlock)) + { + } + + public override void Write(ICodeWriter writer, object o) + { + writer.BeginNewLine(true); + base.Write(writer, o); + } + + public CSCodeBlock TryBlock { get; private set; } + public CodeElementCollection CatchBlocks { get; private set; } + } +} diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSType.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSType.cs new file mode 100644 index 000000000000..768f4ef7fea2 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSType.cs @@ -0,0 +1,278 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; +using System.IO; +using System.Text; +using System.Linq; +using System.Collections.Generic; + +namespace SyntaxDynamo.CSLang +{ + public abstract class CSType : DelegatedSimpleElement + { + public override string ToString() => CodeWriter.WriteToString(this); + + public abstract CSFunctionCall Typeof(); + public abstract CSFunctionCall Default(); + public abstract CSFunctionCall Ctor(); + + public static CSType Copy(CSType csType) + { + if (csType is CSSimpleType csSimpleType) + { + return new CSSimpleType(csSimpleType); + } + if (csType is CSGenericReferenceType csGen) + { + return new CSGenericReferenceType(csGen); + } + throw new NotImplementedException($"Type {csType.GetType().Name} needs a copy constructor"); + } + } + + public class CSSimpleType : CSType + { + public CSSimpleType(Type t) + : this(t.Name) + { + } + public CSSimpleType(string name) + : this(name, false) + { + } + + public CSSimpleType(CSSimpleType csSimpleType) + : this(csSimpleType.Name, csSimpleType.IsArray) + { + if (csSimpleType.GenericTypes != null) + { + GenericTypes = new CSType[csSimpleType.GenericTypes.Length]; + for (int i = 0; i < GenericTypes.Length; i++) + { + GenericTypes[i] = CSType.Copy(csSimpleType.GenericTypes[i]); + } + } + } + + public CSSimpleType(string name, bool isArray) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + hiddenName = name + (isArray ? "[]" : ""); + } + + public static explicit operator CSSimpleType(string name) + { + return new CSSimpleType(name); + } + + public static CSSimpleType CreateArray(string name) + { + return new CSSimpleType(name, true); + } + + public CSSimpleType(string name, bool isArray, params CSType[] genericSpecialization) + { + ArgumentNullException.ThrowIfNull(name, nameof(name)); + IsGeneric = genericSpecialization != null && genericSpecialization.Length > 0; + GenericTypes = genericSpecialization; + GenericTypeName = name; + IsArray = isArray; + } + + public CSSimpleType(string name, bool isArray, params string[] genericSpecialization) + : this(name, isArray, genericSpecialization.Select(s => new CSSimpleType(s)).ToArray()) + { + } + + string hiddenName; + public string Name + { + get + { + return hiddenName ?? GenerateName(); + } + } + public bool IsGeneric { get; private set; } + public string GenericTypeName { get; private set; } + public CSType[] GenericTypes { get; private set; } + public bool IsArray { get; private set; } + public bool IsPointer { get; private set; } + + string GenerateName() + { + StringBuilder sb = new StringBuilder(); + sb.Append(GenericTypeName); + if (GenericTypes != null && GenericTypes.Length > 0) + { + sb.Append("<"); + int i = 0; + foreach (CSType type in GenericTypes) + { + if (i > 0) + sb.Append(", "); + sb.Append(type.ToString()); + i++; + } + sb.Append(">"); + } + if (IsArray) + sb.Append("[]"); + return sb.ToString(); + } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write(Name, false); + } + + public override CSFunctionCall Typeof() + { + return new CSFunctionCall("typeof", false, new CSIdentifier(Name)); + } + + public override CSFunctionCall Default() + { + return new CSFunctionCall("default", false, new CSIdentifier(Name)); + } + + public override CSFunctionCall Ctor() + { + return new CSFunctionCall(Name, true); + } + + static CSSimpleType + tBool = new CSSimpleType("bool"), + tChar = new CSSimpleType("char"), + tSbyte = new CSSimpleType("sbyte"), + tShort = new CSSimpleType("short"), + tInt = new CSSimpleType("int"), + tLong = new CSSimpleType("long"), + tFloat = new CSSimpleType("float"), + tByte = new CSSimpleType("byte"), + tUshort = new CSSimpleType("ushort"), + tUint = new CSSimpleType("uint"), + tUlong = new CSSimpleType("ulong"), + tDouble = new CSSimpleType("double"), + tString = new CSSimpleType("string"), + tObject = new CSSimpleType("object"), + tIntPtr = new CSSimpleType("IntPtr"), + tVoid = new CSSimpleType("void"), + tByteStar = new CSSimpleType("byte").Star, + tType = new CSSimpleType("Type"), + tVar = new CSSimpleType("var"), + tNfloat = new CSSimpleType("nfloat"), + tNint = new CSSimpleType("nint"), + tNUint = new CSSimpleType("nuint") + ; + + public CSSimpleType Star + { + get + { + if (Name.EndsWith("[]")) + { + throw new NotImplementedException("Blindly making an array a pointer doesn't do what you think."); + } + else + { + var ptrType = new CSSimpleType(Name + " *", false); + ptrType.IsPointer = true; + return ptrType; + } + } + } + + public static CSSimpleType Bool { get { return tBool; } } + public static CSSimpleType Char { get { return tChar; } } + public static CSSimpleType SByte { get { return tSbyte; } } + public static CSSimpleType Short { get { return tShort; } } + public static CSSimpleType Int { get { return tInt; } } + public static CSSimpleType Long { get { return tLong; } } + public static CSSimpleType Float { get { return tFloat; } } + public static CSSimpleType Byte { get { return tByte; } } + public static CSSimpleType UShort { get { return tUshort; } } + public static CSSimpleType UInt { get { return tUint; } } + public static CSSimpleType ULong { get { return tUlong; } } + public static CSSimpleType Double { get { return tDouble; } } + public static CSSimpleType String { get { return tString; } } + public static CSSimpleType Object { get { return tObject; } } + public static CSSimpleType IntPtr { get { return tIntPtr; } } + public static CSSimpleType Void { get { return tVoid; } } + public static CSSimpleType ByteStar { get { return tByteStar; } } + public static CSSimpleType Type { get { return tType; } } + public static CSSimpleType Var { get { return tVar; } } + public static CSSimpleType NFloat { get { return tNfloat; } } + public static CSSimpleType NInt => tNint; + public static CSSimpleType NUInt => tNUint; + } + + public class CSGenericReferenceType : CSType + { + public CSGenericReferenceType(int depth, int index) + { + Depth = depth; + Index = index; + InterfaceConstraints = new List(); + } + + public CSGenericReferenceType(CSGenericReferenceType csGeneric) + : this(csGeneric.Depth, csGeneric.Index) + { + foreach (var elem in csGeneric.InterfaceConstraints) + { + InterfaceConstraints.Add(CSType.Copy(elem)); + } + ReferenceNamer = csGeneric.ReferenceNamer; + } + + // this doesn't really belong here, but I'm going to need it. + public List InterfaceConstraints { get; private set; } + + public int Depth { get; private set; } + public int Index { get; private set; } + public Func ReferenceNamer { get; set; } + + protected override void LLWrite(ICodeWriter writer, object o) + { + writer.Write(Name, true); + } + + public string Name + { + get + { + Func namer = ReferenceNamer ?? DefaultNamer; + return namer(Depth, Index); + } + } + + const string kNames = "TUVWABCDEFGHIJKLMN"; + + public static string DefaultNamer(int depth, int index) + { + if (depth < 0 || depth >= kNames.Length) + throw new ArgumentOutOfRangeException(nameof(depth)); + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index)); + return String.Format("{0}{1}", kNames[depth], index); + } + + public override CSFunctionCall Typeof() + { + return new CSFunctionCall("typeof", false, new CSIdentifier(Name)); + } + + public override CSFunctionCall Default() + { + return new CSFunctionCall("default", false, new CSIdentifier(Name)); + } + + public override CSFunctionCall Ctor() + { + return new CSFunctionCall(Name, true); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSUnaryExpression.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSUnaryExpression.cs new file mode 100644 index 000000000000..bf9f21363692 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSUnaryExpression.cs @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public class CSUnaryExpression : CSBaseExpression + { + public CSUnaryExpression(CSUnaryOperator op, ICSExpression expr) + { + ArgumentNullException.ThrowIfNull(expr, nameof(expr)); + Operation = op; + Expr = expr; + } + protected override void LLWrite(ICodeWriter writer, object o) + { + if (IsPostfix(Operation)) + { + Expr.WriteAll(writer); + writer.Write(OperatorToString(Operation), true); + } + else + { + writer.Write(OperatorToString(Operation), true); + Expr.WriteAll(writer); + } + } + + public CSUnaryOperator Operation { get; private set; } + public ICSExpression Expr { get; private set; } + + static string OperatorToString(CSUnaryOperator op) + { + switch (op) + { + case CSUnaryOperator.At: + return "@"; + case CSUnaryOperator.BitNot: + return "~"; + case CSUnaryOperator.Neg: + return "-"; + case CSUnaryOperator.Not: + return "!"; + case CSUnaryOperator.Out: + return "out "; + case CSUnaryOperator.Pos: + return "+"; + case CSUnaryOperator.Ref: + return "ref "; + case CSUnaryOperator.AddressOf: + return "&"; + case CSUnaryOperator.Indirection: + return "*"; + case CSUnaryOperator.Await: + return "await "; + case CSUnaryOperator.PostBang: + return "!"; + case CSUnaryOperator.Question: + return "?"; + default: + throw new ArgumentOutOfRangeException(nameof(op)); + } + } + + static bool IsPostfix(CSUnaryOperator op) + { + return op == CSUnaryOperator.PostBang || op == CSUnaryOperator.Question; + } + + public static CSUnaryExpression AddressOf(ICSExpression expr) + { + return new CSUnaryExpression(CSUnaryOperator.AddressOf, expr); + } + + public static CSUnaryExpression Star(ICSExpression expr) + { + return new CSUnaryExpression(CSUnaryOperator.Indirection, expr); + } + + public static CSUnaryExpression Out(CSIdentifier id) + { + return new CSUnaryExpression(CSUnaryOperator.Out, id); + } + + public static CSUnaryExpression Out(string id) + { + return Out(new CSIdentifier(id)); + } + + public static CSUnaryExpression Ref(CSIdentifier id) + { + return new CSUnaryExpression(CSUnaryOperator.Ref, id); + } + + public static CSUnaryExpression Ref(string id) + { + return Ref(new CSIdentifier(id)); + } + + public static CSUnaryExpression Await(ICSExpression expr) + { + return new CSUnaryExpression(CSUnaryOperator.Await, expr); + } + + public static CSUnaryExpression PostBang(ICSExpression expr) + { + return new CSUnaryExpression(CSUnaryOperator.PostBang, expr); + } + + public static CSUnaryExpression Question(ICSExpression expr) + { + return new CSUnaryExpression(CSUnaryOperator.Question, expr); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSUsing.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSUsing.cs new file mode 100644 index 000000000000..f822988f4e2a --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/CSUsing.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Linq; +using System.Collections.Generic; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public class CSUsing : SimpleLineElement + { + public CSUsing(string package) + : base(string.Format("using {0};", package), false, false, false) + { + Package = package; + } + + public string Package { get; private set; } + } + + public class CSUsingPackages : CodeElementCollection + { + public CSUsingPackages() : base() { } + public CSUsingPackages(params CSUsing[] use) + : this() + { + AddRange(use); + } + public CSUsingPackages(params string[] use) + : this() + { + AddRange(use.Select(s => new CSUsing(s))); + } + + public CSUsingPackages And(CSUsing use) + { + Add(use); + return this; + } + + public CSUsingPackages And(string package) { return And(new CSUsing(package)); } + + public void AddIfNotPresent(string package, CSIdentifier protectedBy = null) + { + if (String.IsNullOrEmpty(package)) + return; + CSUsing target = new CSUsing(package); + if (!this.Exists(use => use.Contents == target.Contents)) + { + if ((object)protectedBy != null) + { + CSConditionalCompilation.ProtectWithIfEndif(protectedBy, target); + } + Add(target); + } + } + + public void AddIfNotPresent(Type t, CSIdentifier protectedBy = null) + { + AddIfNotPresent(t.Namespace, protectedBy); + } + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/Enums.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/Enums.cs new file mode 100644 index 000000000000..ce005aff06dd --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/Enums.cs @@ -0,0 +1,101 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SyntaxDynamo.CSLang +{ + public enum CSVisibility + { + None = 0, + Public, + Internal, + Protected, + Private, + } + + public enum CSMethodKind + { + None = 0, + Static, + StaticExtern, + StaticNew, + Virtual, + Override, + Extern, + New, + Abstract, + Interface, + Unsafe, + StaticUnsafe, + } + + public enum CSBinaryOperator + { + Add = 0, + Sub, + Mul, + Div, + Mod, + And, + Or, + Less, + Greater, + Equal, + NotEqual, + LessEqual, + GreaterEqual, + BitAnd, + BitOr, + BitXor, + LeftShift, + RightShift, + Dot, + Is, + As, + NullCoalesce, + } + + public enum CSUnaryOperator + { + Neg = 0, + Pos, + At, + Not, + BitNot, + Ref, + Out, + AddressOf, + Indirection, + Await, + PostBang, + Question, + } + + public enum CSAssignmentOperator + { + Assign, + AddAssign, + SubAssign, + MulAssign, + DivAssign, + ModAssign, + AndAssign, + OrAssign, + XorAssign + } + + public enum CSParameterKind + { + None, + Ref, + Out, + Params, + This + } + + public enum CSShortCircuitKind + { + Break, + Continue, + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSExpression.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSExpression.cs new file mode 100644 index 000000000000..9a5ec0708627 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSExpression.cs @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using SyntaxDynamo; + +namespace SyntaxDynamo.CSLang +{ + public interface ICSExpression : ICodeElement + { + } + + public interface ICSExpressionList : ICodeElementSet + { + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSLineable.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSLineable.cs new file mode 100644 index 000000000000..791674cfd022 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSLineable.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public interface ICSLineable + { + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSStatement.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSStatement.cs new file mode 100644 index 000000000000..19e78407deb1 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSStatement.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo.CSLang +{ + public interface ICSStatement + { + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSTopLevelDeclaration.cs b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSTopLevelDeclaration.cs new file mode 100644 index 000000000000..3bd0a33d066d --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.CSLang/ICSTopLevelDeclaration.cs @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +namespace SyntaxDynamo.CSLang +{ + public interface ICSTopLevelDeclaration : ICodeElement + { + } + + public class CSTopLevelDeclations : CodeElementCollection + { + public CSTopLevelDeclations(params ICSTopLevelDeclaration[] decls) + : base() + { + ArgumentNullException.ThrowIfNull(decls, nameof(decls)); + AddRange(decls); + } + + + } +} + diff --git a/src/SyntaxDynamo/src/SyntaxDynamo.csproj b/src/SyntaxDynamo/src/SyntaxDynamo.csproj new file mode 100644 index 000000000000..c93a4aeb0ac9 --- /dev/null +++ b/src/SyntaxDynamo/src/SyntaxDynamo.csproj @@ -0,0 +1,12 @@ + + + Library + net8.0 + enable + disable + true + + + + + diff --git a/src/SyntaxDynamo/src/WriteEventArgs.cs b/src/SyntaxDynamo/src/WriteEventArgs.cs new file mode 100644 index 000000000000..d87a8a42c9f0 --- /dev/null +++ b/src/SyntaxDynamo/src/WriteEventArgs.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace SyntaxDynamo +{ + public class WriteEventArgs : EventArgs + { + public WriteEventArgs(ICodeWriter writer) + { + if (writer == null) + throw new ArgumentNullException(nameof(writer)); + Writer = writer; + } + + public ICodeWriter Writer { get; private set; } + } +} + diff --git a/src/SyntaxDynamo/tests/SyntaxDynamo.Tests.csproj b/src/SyntaxDynamo/tests/SyntaxDynamo.Tests.csproj new file mode 100644 index 000000000000..c5b3f2ab03e1 --- /dev/null +++ b/src/SyntaxDynamo/tests/SyntaxDynamo.Tests.csproj @@ -0,0 +1,12 @@ + + + + net8.0 + enable + enable + + false + true + + + diff --git a/src/SyntaxDynamo/tests/UnitTest1.cs b/src/SyntaxDynamo/tests/UnitTest1.cs new file mode 100644 index 000000000000..6a2bf3f3da9f --- /dev/null +++ b/src/SyntaxDynamo/tests/UnitTest1.cs @@ -0,0 +1,12 @@ +using Xunit; + +namespace SyntaxDynamo.Tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} \ No newline at end of file diff --git a/src/samples/HelloWorld/HelloLibrary.swift b/src/samples/HelloWorld/HelloLibrary.swift new file mode 100644 index 000000000000..028ac3a79b38 --- /dev/null +++ b/src/samples/HelloWorld/HelloLibrary.swift @@ -0,0 +1,3 @@ +public func sayHello() { + print("Hello world") +} \ No newline at end of file diff --git a/src/samples/HelloWorld/HelloWorld.csproj b/src/samples/HelloWorld/HelloWorld.csproj new file mode 100644 index 000000000000..fddc7980db97 --- /dev/null +++ b/src/samples/HelloWorld/HelloWorld.csproj @@ -0,0 +1,8 @@ + + + Exe + net8.0 + enable + disable + + diff --git a/src/samples/HelloWorld/Program.cs b/src/samples/HelloWorld/Program.cs new file mode 100644 index 000000000000..1d3607cd7854 --- /dev/null +++ b/src/samples/HelloWorld/Program.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using HelloLibraryBindings; + +namespace HelloWorld +{ + public class Program + { + public static void Main(string[] args) + { + HelloLibrary.sayHello(); + } + } +} diff --git a/src/samples/HelloWorld/build.sh b/src/samples/HelloWorld/build.sh new file mode 100755 index 000000000000..a2e0b30b8a6b --- /dev/null +++ b/src/samples/HelloWorld/build.sh @@ -0,0 +1,14 @@ +#!/bin/bash +xcrun swiftc -emit-module -emit-library -enable-library-evolution -emit-module-interface HelloLibrary.swift -o libHelloLibrary.dylib + +dotnet restore ../../SwiftBindings/src/SwiftBindings.csproj +dotnet build ../../SwiftBindings/src/SwiftBindings.csproj + +if [ $? -eq 0 ]; then + echo "Build successful. Running the BindingsTool..." + dotnet ../../../artifacts/bin/SwiftBindings/Debug/net8.0/SwiftBindings.dll -a "./HelloLibrary.abi.json" -o "./" + dotnet run +else + echo "Build failed. Exiting..." + exit 1 +fi