diff --git a/.github/workflows/ClingoSharp.CD.yml b/.github/workflows/ClingoSharp.CD.yml new file mode 100644 index 0000000..c50d28d --- /dev/null +++ b/.github/workflows/ClingoSharp.CD.yml @@ -0,0 +1,111 @@ +name: ClingoSharp Publish + +on: + push: + branches: + - master + +jobs: + build-windows: + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + persist-credentials: false + - name: Checkout submodules + run: | + git submodule init + git submodule update + - name: Building dependecies + run: .\build.ps1 + - name: Upload Artifacts + uses: actions/upload-artifact@v1 + with: + name: clingo-windows + path: .\clingo\build\win + + build-linux: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + persist-credentials: false + - name: Checkout submodules + run: | + git submodule init + git submodule update + - name: Building dependecies + run: ./build.sh + - name: Upload Artifacts + uses: actions/upload-artifact@v1 + with: + name: clingo-linux + path: ./clingo/build/linux + + build: + needs: [build-windows, build-linux] + runs-on: windows-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + with: + persist-credentials: false + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 3.1.100 + - name: Download Windows Artifacts + uses: actions/download-artifact@v1 + with: + name: clingo-windows + - name: Download Linux Artifacts + uses: actions/download-artifact@v1 + with: + name: clingo-linux + - name: Installing Artifacts + run: | + Copy-Item -Path '.\clingo-windows\*' -Destination '.\clingo\build\win' -Recurse + Copy-Item -Path '.\clingo-linux\*' -Destination '.\clingo\build\linux' -Recurse + - name: Build + run: dotnet build --configuration Release + - name: Test + run: .\test.ps1 + - name: Setup DocFX + run: choco install docfx -y + - name: Building documentation + run: | + docfx .\docfx.json + if ($lastexitcode -ne 0){ + throw [System.Exception] "docfx build failed with exit code $lastexitcode." + } + - name: Reporting coverage result + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: .\coverage.info + - name: Upload Artifacts + uses: actions/upload-artifact@v1 + with: + name: site + path: _site + + deploy: + needs: [build] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + - name: Download Artifacts # The built project is downloaded into the 'site' folder. + uses: actions/download-artifact@v1 + with: + name: site + - name: Deploy + uses: JamesIves/github-pages-deploy-action@releases/v3 + with: + ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} + BRANCH: gh-pages + FOLDER: "site" # The deployment folder should match the name of the artifact. Even though our project builds into the 'build' folder the artifact name of 'site' must be placed here. \ No newline at end of file diff --git a/.github/workflows/ClingoSharp.CI.yml b/.github/workflows/ClingoSharp.CI.yml index 4c354a4..fcc153c 100644 --- a/.github/workflows/ClingoSharp.CI.yml +++ b/.github/workflows/ClingoSharp.CI.yml @@ -1,9 +1,6 @@ -name: ClingoSharp Workflow +name: ClingoSharp Test on: - push: - branches: - - master pull_request: branches: - develop @@ -12,7 +9,7 @@ on: - bugfix/* jobs: - build: + build-windows: runs-on: windows-latest steps: - name: Checkout repository @@ -23,50 +20,63 @@ jobs: run: | git submodule init git submodule update - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 3.1.100 - name: Building dependecies run: .\build.ps1 - - name: Build - run: dotnet build --configuration Release - - name: Test - run: .\test.ps1 - - name: Setup DocFX - run: choco install docfx -y - - name: Building documentation - run: | - docfx .\docfx.json - if ($lastexitcode -ne 0){ - throw [System.Exception] "docfx build failed with exit code $lastexitcode." - } - - name: Reporting coverage result - uses: coverallsapp/github-action@master - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - path-to-lcov: .\coverage.info - name: Upload Artifacts uses: actions/upload-artifact@v1 with: - name: site - path: _site - - deploy: - needs: [build] + name: clingo-windows + path: .\clingo\build\win + + build-linux: runs-on: ubuntu-latest steps: - - name: Checkout + - name: Checkout repository + uses: actions/checkout@v2 + with: + persist-credentials: false + - name: Checkout submodules + run: | + git submodule init + git submodule update + - name: Building dependecies + run: ./build.sh + - name: Upload Artifacts + uses: actions/upload-artifact@v1 + with: + name: clingo-linux + path: ./clingo/build/linux + + build: + needs: [build-windows, build-linux] + runs-on: windows-latest + steps: + - name: Checkout repository uses: actions/checkout@v2 with: persist-credentials: false - - name: Download Artifacts # The built project is downloaded into the 'site' folder. + - name: Setup .NET Core + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 3.1.100 + - name: Download Windows Artifacts + uses: actions/download-artifact@v1 + with: + name: clingo-windows + - name: Download Linux Artifacts uses: actions/download-artifact@v1 with: - name: site - - name: Deploy - uses: JamesIves/github-pages-deploy-action@releases/v3 + name: clingo-linux + - name: Installing Artifacts + run: | + Copy-Item -Path '.\clingo-windows' -Destination '.\clingo\build\win\' -Recurse + Copy-Item -Path '.\clingo-linux' -Destination '.\clingo\build\linux\' -Recurse + - name: Build + run: dotnet build --configuration Release + - name: Test + run: .\test.ps1 + - name: Reporting coverage result + uses: coverallsapp/github-action@master with: - ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} - BRANCH: gh-pages - FOLDER: "site" # The deployment folder should match the name of the artifact. Even though our project builds into the 'build' folder the artifact name of 'site' must be placed here. \ No newline at end of file + github-token: ${{ secrets.GITHUB_TOKEN }} + path-to-lcov: .\coverage.info diff --git a/.gitignore b/.gitignore index 37baaa3..05fccf7 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ coverage.info *.user *.userosscache *.sln.docstates +nuget.config # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs diff --git a/ClingoSharp.sln b/ClingoSharp.sln index 24ca1f1..56dba25 100644 --- a/ClingoSharp.sln +++ b/ClingoSharp.sln @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClingoSharp.NativeWrapper", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClingoSharp.CoreServices", "src\ClingoSharp.CoreServices\ClingoSharp.CoreServices.csproj", "{FD343390-4193-4981-B985-4FA0767B77A1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClingoSharp.Test", "tests\ClingoSharp.Test.csproj", "{E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClingoSharp.Tests", "tests\ClingoSharp.Tests.csproj", "{E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{498A4F49-6B6C-4A39-932D-9F7F41DCE625}" EndProject @@ -29,10 +29,6 @@ Global {AD231050-B939-48E7-8D5B-5D313C44B8B8}.Debug|Any CPU.Build.0 = Debug|Any CPU {AD231050-B939-48E7-8D5B-5D313C44B8B8}.Release|Any CPU.ActiveCfg = Release|Any CPU {AD231050-B939-48E7-8D5B-5D313C44B8B8}.Release|Any CPU.Build.0 = Release|Any CPU - {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Release|Any CPU.Build.0 = Release|Any CPU {F85762B3-1F18-404A-9778-8066F74E486A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F85762B3-1F18-404A-9778-8066F74E486A}.Debug|Any CPU.Build.0 = Debug|Any CPU {F85762B3-1F18-404A-9778-8066F74E486A}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -41,6 +37,10 @@ Global {FD343390-4193-4981-B985-4FA0767B77A1}.Debug|Any CPU.Build.0 = Debug|Any CPU {FD343390-4193-4981-B985-4FA0767B77A1}.Release|Any CPU.ActiveCfg = Release|Any CPU {FD343390-4193-4981-B985-4FA0767B77A1}.Release|Any CPU.Build.0 = Release|Any CPU + {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E26B31EE-8CF9-43E7-A8F7-E7D7EF283A73}.Release|Any CPU.Build.0 = Release|Any CPU {166D0AD3-F1FE-4519-A7B0-76C6F653B584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {166D0AD3-F1FE-4519-A7B0-76C6F653B584}.Debug|Any CPU.Build.0 = Debug|Any CPU {166D0AD3-F1FE-4519-A7B0-76C6F653B584}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/README.md b/README.md index 60bca77..e4232ec 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Clingo# (ClingoSharp) -[![.NET Standard v2.0](https://img.shields.io/badge/.NET%20Standard-2.0-7014e8)](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) +[![.NET Core v3.0](https://img.shields.io/badge/.NET%20Core-3.0-7014e8)](https://dotnet.microsoft.com/download/dotnet-core/3.0) +[![.NET Framework v4.8](https://img.shields.io/badge/.NET%20Framework-4.8-7014e8)](https://dotnet.microsoft.com/download/dotnet-framework/net48) [![Clingo 5.4.0](https://img.shields.io/badge/Clingo-5.4.0-blue)](https://github.com/potassco/clingo) ![ClingoSharp Workflow](https://github.com/NEKERAFA/ClingoSharp/workflows/ClingoSharp%20Workflow/badge.svg?branch=master&event=push) [![Coverage Status](https://coveralls.io/repos/github/NEKERAFA/ClingoSharp/badge.svg?branch=master)](https://coveralls.io/github/NEKERAFA/ClingoSharp?branch=master) diff --git a/build.ps1 b/build.ps1 index ff931a7..ff12acd 100644 --- a/build.ps1 +++ b/build.ps1 @@ -10,17 +10,8 @@ Write-Host "" Write-Host "Compiling clingo..." -ForegroundColor Green -Write-Host "Compiling Win32 version..." -ForegroundColor Yellow - -cmake "clingo" -B".\clingo\build\win\x86" -DCLINGO_BUILD_SHARED=ON -DCLINGO_BUILD_WITH_PYTHON=OFF -DCLINGO_BUILD_WITH_LUA=OFF -DCLINGO_BUILD_APPS=OFF -G "Visual Studio 16 2019" -A Win32 -cmake --build ".\clingo\build\win\x86" --config Release - -Write-Host "" - -Write-Host "Compiling Windows x64 version..." -ForegroundColor Yellow - -cmake "clingo" -B".\clingo\build\win\x64" -DCLINGO_BUILD_SHARED=ON -DCLINGO_BUILD_WITH_PYTHON=OFF -DCLINGO_BUILD_WITH_LUA=OFF -DCLINGO_BUILD_APPS=OFF -G "Visual Studio 16 2019" -A x64 -cmake --build ".\clingo\build\win\x64" --config Release +cmake "clingo" -B".\clingo\build\win" -DCLINGO_BUILD_SHARED=ON -DCLINGO_BUILD_WITH_PYTHON=OFF -DCLINGO_BUILD_WITH_LUA=OFF -DCLINGO_BUILD_APPS=OFF -G "Visual Studio 16 2019" -A x64 +cmake --build ".\clingo\build\win" --config Release Write-Host "" diff --git a/build.sh b/build.sh old mode 100644 new mode 100755 index 6934259..30cffcd --- a/build.sh +++ b/build.sh @@ -1,56 +1,16 @@ echo -e "\033[92mClearing working directory...\033[0m" -if [ -f "./clingo/build/linux/i386"]; then - echo -e "\033[93mDeleting ./clingo/build/linux/i386...\033[0m" - rm -r "./clingo/build/linux/i386" -fi - -if [ -f "./clingo/build/linux/amd64"]; then - echo -e "\033[93mDeleting ./clingo/build/linux/amd64...\033[0m" - rm -r "./clingo/build/linux/amd64" -fi - -if [ -f "./src/ClingoSharp/runtimes/linux/i386"]; then - echo -e "\033[93mDeleting ./src/ClingoSharp/runtimes/linux/i386...\033[0m" - rm -r "./src/ClingoSharp/runtimes/linux/i386" -fi - -if [ -f "./src/ClingoSharp/runtimes/linux/amd64"]; then - echo -e "\033[93mDeleting ./src/ClingoSharp/runtimes/linux/amd64...\033[0m" - rm -r "./src/ClingoSharp/runtimes/linux/amd64" +if [ -d "./clingo/build/linux" ]; then + echo -e "\033[93mDeleting ./clingo/build/linux...\033[0m" + rm -r "./clingo/build/linux" fi echo "" echo -e "\033[92mCompiling clingo...\033[0m" -echo -e "\033[93mCompiling Linux x86 version...\033[0m" - -cmake "clingo" -B"./clingo/build/linux/i386" -DCLINGO_BUILD_SHARED=ON -DCLINGO_BUILD_WITH_PYTHON=OFF -DCLINGO_BUILD_WITH_LUA=OFF -DCLINGO_BUILD_APPS=OFF -m32 -cmake --build "./clingo/build/linux/i368" -DCMAKE_BUILD_TYPE=Release - -echo -e "\033[93mCopying Linux x86 version to ./src/ClingoSharp/runtimes/linux-i386/native...\033[0m" -mkdir -p "./src/ClingoSharp/runtimes/linux-i386/native" -cp "./clingo/build/linux/i386/clingo.so" "./src/ClingoSharp/runtimes/linux-i386/native" - -echo -e "\033[93mCopying Linux x86 version to ./tests/runtimes/linux-i386/native...\033[0m" -mkdir -p "./tests/runtimes/linux-i386/native" -cp "./clingo/build/linux/i386/clingo.so" "./tests/runtimes/linux-i386/native" - -echo "" - -echo -e "\033[93mCompiling Linux x64 version...\033[0m" - -cmake "clingo" -B"./clingo/build/linux/amd64" -DCLINGO_BUILD_SHARED=ON -DCLINGO_BUILD_WITH_PYTHON=OFF -DCLINGO_BUILD_WITH_LUA=OFF -DCLINGO_BUILD_APPS=OFF -m64 -cmake --build "./clingo/build/linux/amd64" -DCMAKE_BUILD_TYPE=Release - -echo -e "\033[93mCopying Linux x64 version to ./src/ClingoSharp/runtimes/linux-amd64/native...\033[0m" -mkdir -p "./src/ClingoSharp/runtimes/linux-amd64/native" -cp "./clingo/build/linux/amd64/clingo.so" "./src/ClingoSharp/runtimes/linux-amd64/native" - -echo -e "\033[93mCopying Linux x64 version to ./tests/runtimes/linux-amd64/native...\033[0m" -mkdir -p "./tests/runtimes/linux-amd64/native" -cp "./clingo/build/linux/amd64/clingo.so" "./tests/runtimes/linux-amd64/native" +cmake -B"./clingo/build/linux" -DCLINGO_BUILD_SHARED=ON -DCLINGO_BUILD_WITH_PYTHON=OFF -DCLINGO_BUILD_WITH_LUA=OFF -DCLINGO_BUILD_APPS=OFF "clingo" +cmake --build "./clingo/build/linux" echo "" diff --git a/examples/InspectionModel/Program.cs b/examples/InspectionModel/Program.cs index abf2bdd..facb876 100644 --- a/examples/InspectionModel/Program.cs +++ b/examples/InspectionModel/Program.cs @@ -1,6 +1,8 @@ using ClingoSharp; using System; using System.Collections.Generic; +using System.IO; +using System.Reflection; namespace ClingoSharpApp { @@ -11,7 +13,13 @@ static void Main(string[] args) Console.WriteLine($"Clingo {Clingo.Version}\n"); Control ctl = new Control(new List() { "0" }); - ctl.Add("base", new List() { }, "{a; b}."); + + string filename = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "program.lp"); + Console.WriteLine(filename); + ctl.Load(filename); + + + //ctl.Add("base", new List() { }, "{a; b}."); var parts = new List>>() { new Tuple>("base", new List() {}), @@ -36,6 +44,7 @@ static void Main(string[] args) { continue; } + } } } \ No newline at end of file diff --git a/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.csproj b/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.csproj index 64d2659..79953e8 100644 --- a/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.csproj +++ b/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1;netstandard2.0 + netcoreapp3.0;net48 Rafael Alcalde Azpiazu <rafael.alcalde.azpiazu@udc.es> University of A Coruña Copyright© Rafael Alcalde Azpiazu - 2019 @@ -13,11 +13,11 @@ clingo bindings logic-programing answer-set-programming Library MIT - 0.0.1.0 - 0.0.1.0 - 0.0.1-alpha + 0.0.3.1 + 0.0.3.1 + 0.0.3-alpha1 true - First version + Added Clingo.Control.Load(string) function true @@ -26,21 +26,9 @@ - - - true - - - true - - + + + diff --git a/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.targets b/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.targets index f72112b..4c34aa9 100644 --- a/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.targets +++ b/src/ClingoSharp.CoreServices/ClingoSharp.CoreServices.targets @@ -2,16 +2,16 @@ - - + + - - + + - - + + \ No newline at end of file diff --git a/src/ClingoSharp.CoreServices/Interfaces/Modules/IControlModule.cs b/src/ClingoSharp.CoreServices/Interfaces/Modules/IControlModule.cs index 7254625..7280060 100644 --- a/src/ClingoSharp.CoreServices/Interfaces/Modules/IControlModule.cs +++ b/src/ClingoSharp.CoreServices/Interfaces/Modules/IControlModule.cs @@ -33,6 +33,14 @@ public interface IControlModule : Interfaces.IClingoModule #region Grounding Functions + /// + /// + /// + /// + /// + /// + bool Load(Control control, string filename); + /// /// Extend the logic program with the given non-ground logic program in string form. /// This function puts the given program into a block of form: #program name(parameters). diff --git a/src/ClingoSharp.CoreServices/Shared/ClingoContext.cs b/src/ClingoSharp.CoreServices/Shared/ClingoContext.cs index 6ece705..49d5a58 100644 --- a/src/ClingoSharp.CoreServices/Shared/ClingoContext.cs +++ b/src/ClingoSharp.CoreServices/Shared/ClingoContext.cs @@ -47,17 +47,19 @@ private IntPtr LoadNativeClingoLibrary() string nativeLibraryFolder; // Gets the extension of the native libray string extension; + // Gets the prefix of the native library + string prefix; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - var arch = Environment.Is64BitProcess ? "x64" : "x86"; - nativeLibraryFolder = $"win-{arch}"; + nativeLibraryFolder = $"win"; + prefix = ""; extension = "dll"; } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { - var arch = Environment.Is64BitProcess ? "amd64" : "i386"; - nativeLibraryFolder = $"linux-{arch}"; + nativeLibraryFolder = $"linux"; + prefix = "lib"; extension = "so"; } else @@ -66,7 +68,7 @@ private IntPtr LoadNativeClingoLibrary() } // Loads clingo library - return LoadUnmanagedDllFromPath(Path.Combine(assemblyFolder, "runtimes", nativeLibraryFolder, "native", $"clingo.{extension}")); + return LoadUnmanagedDllFromPath(Path.Combine(assemblyFolder, "runtimes", nativeLibraryFolder, "native", $"{prefix}clingo.{extension}")); } #endregion diff --git a/src/ClingoSharp.NativeWrapper/ClingoSharp.NativeWrapper.csproj b/src/ClingoSharp.NativeWrapper/ClingoSharp.NativeWrapper.csproj index 2e1ece1..cf03ddd 100644 --- a/src/ClingoSharp.NativeWrapper/ClingoSharp.NativeWrapper.csproj +++ b/src/ClingoSharp.NativeWrapper/ClingoSharp.NativeWrapper.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1;netstandard2.0 + netcoreapp3.0;net48 Rafael Alcalde Azpiazu <rafael.alcalde.azpiazu@udc.es> University of A Coruña A C# wrapper to the native C clingo library. @@ -13,12 +13,12 @@ ClingoSharp.NativeWrapper Library MIT - 0.0.1.0 - 0.0.1.0 - 0.0.1-alpha + 0.0.2.1 + 0.0.2.1 + 0.0.2-alpha1 true true - First version + Added Clingo.Control.Load(string) function diff --git a/src/ClingoSharp.NativeWrapper/ControlModuleImpl.cs b/src/ClingoSharp.NativeWrapper/ControlModuleImpl.cs index 3c8aa52..8ed7e7e 100644 --- a/src/ClingoSharp.NativeWrapper/ControlModuleImpl.cs +++ b/src/ClingoSharp.NativeWrapper/ControlModuleImpl.cs @@ -19,7 +19,7 @@ namespace ClingoSharp.NativeWrapper /// Functions to control the grounding and solving process. /// class ControlModuleImpl : IControlModule - { + { private readonly IMapper m_mapper; #region Constructor @@ -69,6 +69,9 @@ public ControlModuleImpl() [DllImport(Constants.ClingoLib, CallingConvention = CallingConvention.Cdecl)] private static extern int clingo_control_ground(IntPtr control, clingo_part[] parts, UIntPtr parts_size, clingo_ground_callback ground_callback, IntPtr ground_callback_data); + [DllImport(Constants.ClingoLib, CallingConvention = CallingConvention.Cdecl)] + private static extern int clingo_control_load(IntPtr control, string filename); + #endregion #region Solving Functions @@ -123,6 +126,13 @@ public void Free(Control control) #region Grounding Functions + public bool Load(Control control, string filename) + { + var success = clingo_control_load(control.Object, filename); + + return success != 0; + } + public bool Add(Control control, string name, string[] parameters, string program) { UIntPtr parametersSize = new UIntPtr(Convert.ToUInt32(parameters == null ? 0 : parameters.Length)); diff --git a/src/ClingoSharp/Clingo.cs b/src/ClingoSharp/Clingo.cs index 89c0db6..20c4388 100644 --- a/src/ClingoSharp/Clingo.cs +++ b/src/ClingoSharp/Clingo.cs @@ -83,6 +83,27 @@ internal static void HandleClingoError(bool success) } } + internal static void HandleClingoWarning(WarningCode code, string message) + { + switch(code) + { + case WarningCode.OperationUndefined: + throw new OperationUndefinedException(message); + case WarningCode.RuntimeError: + throw new RuntimeException(message); + case WarningCode.AtomUndefined: + throw new AtomUndefinedException(message); + case WarningCode.FileIncluded: + throw new FileIncludedException(message); + case WarningCode.VariableUnbounded: + throw new VariableUnboundedException(message); + case WarningCode.GlobalVariable: + throw new GlobalVariableException(message); + case WarningCode.Other: + throw new UnknownException(message); + } + } + /// /// Gets the asociated API module in clingo /// diff --git a/src/ClingoSharp/ClingoSharp.csproj b/src/ClingoSharp/ClingoSharp.csproj index a1e7a15..3bd6b1b 100644 --- a/src/ClingoSharp/ClingoSharp.csproj +++ b/src/ClingoSharp/ClingoSharp.csproj @@ -1,7 +1,7 @@  - netcoreapp3.1;netstandard2.0 + netcoreapp3.0;net48 Rafael Alcalde Azpiazu <rafael.alcalde.azpiazu@udc.es> University of A Coruña Copyright© Rafael Alcalde Azpiazu - 2019 @@ -13,11 +13,11 @@ ClingoSharp Library MIT - 0.0.1.0 - 0.0.1.0 - 0.0.1-alpha + 0.0.2.1 + 0.0.2.1 + 0.0.2-alpha1 true - First version + Added Clingo.Control.Load(string) function true diff --git a/src/ClingoSharp/Control.cs b/src/ClingoSharp/Control.cs index 1b23bb3..97bbd21 100644 --- a/src/ClingoSharp/Control.cs +++ b/src/ClingoSharp/Control.cs @@ -7,6 +7,7 @@ using ClingoSharp.Enums; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Reflection; using System.Runtime.InteropServices; @@ -70,11 +71,16 @@ public Control(List args = null, Action logger = nu { void loggerCallback(WarningCode code, string message, IntPtr data) { + MessageCode messageCode = Enumeration.GetValue((int)code); + if (logger != null) { - MessageCode messageCode = Enumeration.GetValue((int)code) as MessageCode; logger(messageCode, message); } + else + { + Clingo.HandleClingoWarning(code, message); + } } Clingo.HandleClingoError(m_module.New(args?.ToArray(), loggerCallback, Convert.ToUInt32(messageLimit), out ClingoControl controlPtr)); @@ -88,7 +94,7 @@ void loggerCallback(WarningCode code, string message, IntPtr data) ~Control() { - m_module.Free(m_clingoControl); + Dispose(false); } #endregion @@ -129,6 +135,11 @@ public static implicit operator Control(ClingoControl clingoControl) /// public void Dispose() + { + Dispose(true); + } + + private void Dispose(bool disposing) { if (!disposed) { @@ -137,7 +148,8 @@ public void Dispose() disposed = true; } - GC.SuppressFinalize(this); + if (disposing) + GC.SuppressFinalize(this); } /// @@ -151,6 +163,14 @@ public void Add(string name, List parameters, string program) Clingo.HandleClingoError(m_module.Add(this, name, parameters?.ToArray(), program)); } + public void Load(string filename) + { + if (!File.Exists(filename)) + throw new FileNotFoundException(filename); + + Clingo.HandleClingoError(m_module.Load(this, filename)); + } + /// /// Ground the given list of program parts specified by tuples of names and arguments. /// diff --git a/src/ClingoSharp/Enums/Enumeration.cs b/src/ClingoSharp/Enums/Enumeration.cs index d7fb669..36474a7 100644 --- a/src/ClingoSharp/Enums/Enumeration.cs +++ b/src/ClingoSharp/Enums/Enumeration.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; namespace ClingoSharp.Enums { @@ -14,20 +15,21 @@ public abstract class Enumeration : IEnumeration, IComparable, IEqu /// /// The value of the enumeration /// - public int Value { get; } + public int Value { get; private set; } /// /// The string value of the enumeration /// - public string Name => throw new NotImplementedException(); + public string Name { get; private set; } #endregion #region Constructors - protected Enumeration(int value) + protected Enumeration(int value, string name) { Value = value; + Name = name; } #endregion @@ -35,148 +37,176 @@ protected Enumeration(int value) #region Enumeration methods /// - /// Gets a iterator of the names of the constants in the enumeration + /// Gets a iterator of the constants in the enumeration /// - /// A string iterator with the names of the constants in the enumeration - public static IEnumerable GetNames() + /// An value + /// A iterator with the constants in the enumeration + /// is not a subclass + public static IEnumerable GetValues(Type typeEnum) { - throw new NotImplementedException(); + if (typeEnum.IsSubclassOf(typeof(Enumeration))) + { + var fields = typeEnum.GetProperties(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly); + var values = fields.Select(f => f.GetValue(null)).Cast(); + return values; + } + + throw new ArgumentException("is not an type", "typeEnum"); } /// /// Gets a iterator of the constants in the enumeration /// - /// A iterator with the constants in the enumeration - public static IEnumerable GetValues() + /// An value + /// A iterator with the constants in the enumeration + public static IEnumerable GetValues() where TEnum : IEnumeration { - throw new NotImplementedException(); + return GetValues(typeof(TEnum)).Cast(); } /// - /// Gets the value that has the specified value + /// Gets a iterator of the names of the constants in the enumeration /// - /// The value of a particular enumerated constant in terms - /// The containing the value of the enumerated constant - public static Enumeration GetValue(int value) + /// An value + /// A string iterator with the names of the constants in the enumeration + /// is not a subclass + public static IEnumerable GetNames(Type typeEnum) { - return GetValues().FirstOrDefault(enumeration => enumeration.Value == value); + return GetValues(typeEnum).Select(v => v.Name); } /// - /// Converts the string representation of the name to an equivalent enumerated object + /// Gets a iterator of the names of the constants in the enumeration /// - /// A string containing the name or value to convert - /// true to ignore case; false to regard case. - /// An object whose value is represented by - public static Enumeration Parse(string name, bool ignoreCase) + /// An value + /// A string iterator with the names of the constants in the enumeration + public static IEnumerable GetNames() where TEnum : IEnumeration { - if (string.IsNullOrWhiteSpace(name)) - { - if (name == null) - { - throw new ArgumentNullException(); - } - else - { - throw new ArgumentException(); - } - } + return GetNames(typeof(TEnum)); + } - if (!TryParse(name, ignoreCase, out Enumeration enumeration)) - { - throw new ArgumentException(); - } + /// + /// Gets the value that has the specified value + /// + /// An value + /// The value of a particular enumerated constant in terms + /// The containing the value of the enumerated constant + /// is not a subclass + /// not contains a instance with the value + public static IEnumeration GetValue(Type typeEnum, int value) + { + IEnumeration enumValue = GetValues(typeEnum).FirstOrDefault(enumeration => enumeration.Value == value); + if (enumValue == null) + throw new ArgumentOutOfRangeException("value"); - return enumeration; + return enumValue; } /// - /// Converts the string representation of the name to an equivalent enumerated object + /// Gets the value that has the specified value /// - /// A string containing the name or value to convert - /// An object whose value is represented by - public static Enumeration Parse(string name) + /// An value + /// The value of a particular enumerated constant in terms + /// The containing the value of the enumerated constant + /// not contains a instance with the value + public static TEnum GetValue(int value) where TEnum : IEnumeration { - return Parse(name, false); + return (TEnum) GetValue(typeof(TEnum), value); } /// /// Converts the string representation of the name to an equivalent enumerated object /// - /// The enumeration type to which to convert + /// An value /// A string containing the name or value to convert /// true to ignore case; false to regard case. - /// An object whose value is represented by - public static TEnum Parse(string name, bool ignoreCase) where TEnum : Enumeration + /// When this method returns true, an object containing an enumeration constant representing the parsed value. + /// true if the conversion succeeded; false otherwise. + /// is not a subclass + public static bool TryParse(Type typeEnum, string name, bool ignoreCase, out IEnumeration result) { - return (TEnum)Parse(name, ignoreCase); + result = GetValues(typeEnum).FirstOrDefault(symbolType => symbolType.Name.Equals(name, ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture)); + return result != default; } /// /// Converts the string representation of the name to an equivalent enumerated object /// - /// The enumeration type to which to convert + /// An value /// A string containing the name or value to convert - /// An object whose value is represented by - public static TEnum Parse(string name) where TEnum : Enumeration + /// When this method returns true, an object containing an enumeration constant representing the parsed value. + /// true if the conversion succeeded; false otherwise. + /// is not a subclass + public static bool TryParse(Type typeEnum, string name, out IEnumeration result) { - return (TEnum)Parse(name, false); + return TryParse(typeEnum, name, false, out result); } /// /// Converts the string representation of the name to an equivalent enumerated object /// + /// An value /// A string containing the name or value to convert /// true to ignore case; false to regard case. - /// When this method returns true, an object containing an enumeration constant representing the parsed value. + /// When this method returns true, an object containing an enumeration constant representing the parsed value. /// true if the conversion succeeded; false otherwise. - public static bool TryParse(string name, bool ignoreCase, out Enumeration result) + public static bool TryParse(string name, bool ignoreCase, out TEnum enumeration) { - result = GetValues().FirstOrDefault(symbolType => symbolType.Name.Equals(name, ignoreCase ? StringComparison.InvariantCultureIgnoreCase : StringComparison.InvariantCulture)); - return result == default; + bool parsed = TryParse(typeof(TEnum), name, ignoreCase, out IEnumeration result); + enumeration = (TEnum)result; + return parsed; } /// /// Converts the string representation of the name to an equivalent enumerated object /// + /// An value /// A string containing the name or value to convert - /// When this method returns true, an object containing an enumeration constant representing the parsed value. + /// When this method returns true, an object containing an enumeration constant representing the parsed value. /// true if the conversion succeeded; false otherwise. - public static bool TryParse(string name, out Enumeration result) + public static bool TryParse(string name, out TEnum enumeration) { - return TryParse(name, false, out result); + return TryParse(name, false, out enumeration); } /// /// Converts the string representation of the name to an equivalent enumerated object /// - /// The enumeration type to which to convert + /// An value /// A string containing the name or value to convert /// true to ignore case; false to regard case. - /// When this method returns true, an object containing an enumeration constant representing the parsed value. - /// - public static bool TryParse(string name, bool ignoreCase, out TEnum result) where TEnum : Enumeration + /// is null + /// is empty + /// is not a subclass + /// not contains a instance with the name value + public static IEnumeration Parse(Type typeEnum, string name, bool ignoreCase = false) { - if (TryParse(name, ignoreCase, out Enumeration enumeration)) + if (string.IsNullOrWhiteSpace(name)) { - result = (TEnum)enumeration; - return true; + if (name == null) + throw new ArgumentNullException("name"); + + throw new ArgumentException("cannot be empty", "name"); } - result = default; - return false; + if (!TryParse(typeEnum, name, ignoreCase, out IEnumeration result)) + throw new ArgumentException($"<{typeEnum.Name}> not contains a instance with the name {name}"); + + return result; } /// /// Converts the string representation of the name to an equivalent enumerated object /// - /// The enumeration type to which to convert + /// An value /// A string containing the name or value to convert - /// When this method returns true, an object containing an enumeration constant representing the parsed value. - /// - public static bool TryParse(string name, out TEnum result) where TEnum : Enumeration + /// true to ignore case; false to regard case. + /// is null + /// is empty + /// not contains a instance with the name value + public static TEnum Parse(string name, bool ignoreCase = false) where TEnum : IEnumeration { - return TryParse(name, false, out result); + return (TEnum)Parse(typeof(TEnum), name, ignoreCase); } #endregion @@ -215,6 +245,12 @@ public override int GetHashCode() return Value.GetHashCode() ^ Name.GetHashCode(); } + /// + public override string ToString() + { + return $"{GetType().FullName}.{Name}"; + } + #endregion } } diff --git a/src/ClingoSharp/Exceptions/AtomUndefinedException.cs b/src/ClingoSharp/Exceptions/AtomUndefinedException.cs new file mode 100644 index 0000000..604bcfe --- /dev/null +++ b/src/ClingoSharp/Exceptions/AtomUndefinedException.cs @@ -0,0 +1,10 @@ +using System; + +namespace ClingoSharp.Exceptions +{ + class AtomUndefinedException : Exception + { + public AtomUndefinedException() : base() { } + public AtomUndefinedException(string message) : base(message) { } + } +} diff --git a/src/ClingoSharp/Exceptions/FileIncludedException.cs b/src/ClingoSharp/Exceptions/FileIncludedException.cs new file mode 100644 index 0000000..bc0e1d0 --- /dev/null +++ b/src/ClingoSharp/Exceptions/FileIncludedException.cs @@ -0,0 +1,10 @@ +using System; + +namespace ClingoSharp.Exceptions +{ + class FileIncludedException : Exception + { + public FileIncludedException() : base() { } + public FileIncludedException(string message) : base(message) { } + } +} diff --git a/src/ClingoSharp/Exceptions/GlobalVariableException.cs b/src/ClingoSharp/Exceptions/GlobalVariableException.cs new file mode 100644 index 0000000..9966a17 --- /dev/null +++ b/src/ClingoSharp/Exceptions/GlobalVariableException.cs @@ -0,0 +1,10 @@ +using System; + +namespace ClingoSharp.Exceptions +{ + class GlobalVariableException : Exception + { + public GlobalVariableException() : base() { } + public GlobalVariableException(string message) : base(message) { } + } +} diff --git a/src/ClingoSharp/Exceptions/OperationUndefinedException.cs b/src/ClingoSharp/Exceptions/OperationUndefinedException.cs new file mode 100644 index 0000000..7d6bc34 --- /dev/null +++ b/src/ClingoSharp/Exceptions/OperationUndefinedException.cs @@ -0,0 +1,9 @@ +using System; +namespace ClingoSharp.Exceptions +{ + class OperationUndefinedException : Exception + { + public OperationUndefinedException() : base() { } + public OperationUndefinedException(string message) : base(message) { } + } +} diff --git a/src/ClingoSharp/Exceptions/VariableUnboundedException.cs b/src/ClingoSharp/Exceptions/VariableUnboundedException.cs new file mode 100644 index 0000000..60e23a5 --- /dev/null +++ b/src/ClingoSharp/Exceptions/VariableUnboundedException.cs @@ -0,0 +1,10 @@ +using System; + +namespace ClingoSharp.Exceptions +{ + class VariableUnboundedException : Exception + { + public VariableUnboundedException() : base() { } + public VariableUnboundedException(string message) : base(message) { } + } +} diff --git a/src/ClingoSharp/MessageCode.cs b/src/ClingoSharp/MessageCode.cs index b565f0d..0787657 100644 --- a/src/ClingoSharp/MessageCode.cs +++ b/src/ClingoSharp/MessageCode.cs @@ -1,5 +1,4 @@ using ClingoSharp.Enums; -using System.Collections.Generic; namespace ClingoSharp { @@ -25,41 +24,46 @@ public sealed class MessageCode : Enumeration #region Class Properties + /// + /// Inform about an undefined arithmetic operation or unsupported weight of an aggregate. + /// public static MessageCode OperationUndefined => new MessageCode(0); + + /// + /// To report multiple errors; a corresponding runtime error is raised later. + /// public static MessageCode RuntimeError => new MessageCode(1); + + /// + /// Informs about an undefined atom in program. + /// public static MessageCode AtomUndefined => new MessageCode(2); + + /// + /// Indicates that the same file was included multiple times. + /// public static MessageCode FileIncluded => new MessageCode(3); - public static MessageCode VariableUnbounded => new MessageCode(4); - public static MessageCode GlobalVariable => new MessageCode(5); - public static MessageCode Other => new MessageCode(6); - #endregion + /// + /// Informs about a CSP variable with an unbounded domain. + /// + public static MessageCode VariableUnbounded => new MessageCode(4); - #region Instance Properties + /// + /// Informs about a global variable in a tuple of an aggregate element. + /// + public static MessageCode GlobalVariable => new MessageCode(5); - public new string Name => MessageCodeNames[Value]; + /// + /// Reports other kinds of messages. + /// + public static MessageCode Other => new MessageCode(6); #endregion #region Constructors - private MessageCode(int value) : base(value) { } - - #endregion - - #region Class methods - - /// - public new static IEnumerable GetNames() - { - return (string[])MessageCodeNames.Clone(); - } - - /// - public new static IEnumerable GetValues() - { - return new MessageCode[] { OperationUndefined, RuntimeError, AtomUndefined, FileIncluded, VariableUnbounded, GlobalVariable, Other }; - } + private MessageCode(int value) : base(value, MessageCodeNames[value]) { } #endregion @@ -87,12 +91,6 @@ public override bool Equals(Enumeration other) return Value.Equals(other.Value); } - /// - public override string ToString() - { - return $"CligoSharp.MessageCode<{Name}>"; - } - #endregion } } diff --git a/src/ClingoSharp/ModelType.cs b/src/ClingoSharp/ModelType.cs index 2ce49f4..cc862e9 100644 --- a/src/ClingoSharp/ModelType.cs +++ b/src/ClingoSharp/ModelType.cs @@ -1,5 +1,4 @@ using ClingoSharp.Enums; -using System.Collections.Generic; namespace ClingoSharp { @@ -38,31 +37,9 @@ public sealed class ModelType : Enumeration #endregion - #region Instance Properties - - public new string Name => ModelTypeNames[Value]; - - #endregion - #region Constructors - private ModelType(int value) : base(value) { } - - #endregion - - #region Class methods - - /// - public new static IEnumerable GetNames() - { - return (string[])ModelTypeNames.Clone(); - } - - /// - public new static IEnumerable GetValues() - { - return new ModelType[] { StableModel, BraveConsequences, CautiousConsequences }; - } + private ModelType(int value) : base(value, ModelTypeNames[value]) { } #endregion @@ -90,12 +67,6 @@ public override bool Equals(Enumeration other) return Value.Equals(other.Value); } - /// - public override string ToString() - { - return $"CligoSharp.ModelType<{Name}>"; - } - #endregion } } \ No newline at end of file diff --git a/src/ClingoSharp/SymbolType.cs b/src/ClingoSharp/SymbolType.cs index d602462..5daced4 100644 --- a/src/ClingoSharp/SymbolType.cs +++ b/src/ClingoSharp/SymbolType.cs @@ -1,5 +1,4 @@ using ClingoSharp.Enums; -using System.Collections.Generic; namespace ClingoSharp { @@ -12,7 +11,7 @@ public sealed class SymbolType : Enumeration private static string[] SymbolNames => new string[] { - "Infimun", + "Infimum", "Number", "String", "Function", @@ -23,39 +22,36 @@ public sealed class SymbolType : Enumeration #region Class Properties + /// + /// The #inf symbol. + /// public static SymbolType Infimum => new SymbolType(0); + + /// + /// A numeric symbol, e.g., 1. + /// public static SymbolType Number => new SymbolType(1); - public static SymbolType String => new SymbolType(2); - public static SymbolType Function => new SymbolType(3); - public static SymbolType Supremum => new SymbolType(4); - #endregion + /// + /// A string symbol, e.g., "a". + /// + public static SymbolType String => new SymbolType(2); - #region Instance Properties + /// + /// A function symbol, e.g., c, (1, "a") or f(1, "a"). + /// + public static SymbolType Function => new SymbolType(3); - public new string Name => SymbolNames[Value]; + /// + /// The #sup symbol. + /// + public static SymbolType Supremum => new SymbolType(4); #endregion #region Constructors - private SymbolType(int value) : base(value) { } - - #endregion - - #region Class Methods - - /// - public new static IEnumerable GetNames() - { - return (string[])SymbolNames.Clone(); - } - - /// - public new static IEnumerable GetValues() - { - return new SymbolType[] { Infimum, Number, String, Function, Supremum }; - } + private SymbolType(int value) : base(value, SymbolNames[value]) { } #endregion @@ -83,12 +79,6 @@ public override bool Equals(Enumeration other) return Value.Equals(other.Value); } - /// - public override string ToString() - { - return $"CligoSharp.SymbolType<{Name}>"; - } - #endregion } } \ No newline at end of file diff --git a/src/ClingoSharp/SymbolicAtom.cs b/src/ClingoSharp/SymbolicAtom.cs index 93716cf..83816f4 100644 --- a/src/ClingoSharp/SymbolicAtom.cs +++ b/src/ClingoSharp/SymbolicAtom.cs @@ -5,6 +5,9 @@ namespace ClingoSharp { + /// + /// Captures a symbolic atom and provides properties to inspect its state + /// public sealed class SymbolicAtom { #region Attributes @@ -16,6 +19,9 @@ public sealed class SymbolicAtom #region Properties + /// + /// Whether the atom is an external atom. + /// public bool IsExternal { get @@ -25,6 +31,9 @@ public bool IsExternal } } + /// + /// Whether the atom is a fact. + /// public bool IsFact { get @@ -34,6 +43,9 @@ public bool IsFact } } + /// + /// The program literal associated with the atom. + /// public int Literal { get @@ -43,6 +55,9 @@ public int Literal } } + /// + /// The representation of the atom in form of a symbol. + /// public Symbol Symbol { get @@ -80,7 +95,7 @@ public static implicit operator int(SymbolicAtom symbolicAtom) #region Constructors - internal SymbolicAtom(ClingoSymbolicAtoms symbolicAtoms, ClingoSymbolicAtomIterator position) + public SymbolicAtom(ClingoSymbolicAtoms symbolicAtoms, ClingoSymbolicAtomIterator position) { m_symbolicAtoms = symbolicAtoms; m_position = position; @@ -90,6 +105,13 @@ internal SymbolicAtom(ClingoSymbolicAtoms symbolicAtoms, ClingoSymbolicAtomItera #region Instance Methods + /// + /// Check if the atom matches the given signature. + /// + /// The name of the function + /// The arity of the function + /// Whether the function matches + /// public bool Match(string name, int arity) { return Symbol.Match(name, arity); diff --git a/src/ClingoSharp/SymbolicAtomIterator.cs b/src/ClingoSharp/SymbolicAtomIterator.cs index ee606ab..06495fe 100644 --- a/src/ClingoSharp/SymbolicAtomIterator.cs +++ b/src/ClingoSharp/SymbolicAtomIterator.cs @@ -5,6 +5,9 @@ namespace ClingoSharp { + /// + /// Implements of . + /// public sealed class SymbolicAtomIterator : IEnumerable { #region Attributes diff --git a/src/ClingoSharp/SymbolicAtoms.cs b/src/ClingoSharp/SymbolicAtoms.cs index afb0873..170c000 100644 --- a/src/ClingoSharp/SymbolicAtoms.cs +++ b/src/ClingoSharp/SymbolicAtoms.cs @@ -5,13 +5,16 @@ using System.Collections.Generic; using ClingoSymbolicAtomIterator = ClingoSharp.CoreServices.Types.SymbolicAtomIterator; using ClingoSymbolicAtoms = ClingoSharp.CoreServices.Types.SymbolicAtoms; -using ClingoSymbol = ClingoSharp.CoreServices.Types.Symbol; using ClingoSignature = ClingoSharp.CoreServices.Types.Signature; using System.Linq; using ClingoSharp.CoreServices.Interfaces; namespace ClingoSharp { + /// + /// This class provides read-only access to the atom base of the grounder. + /// It implements of and of < , >. + /// public sealed class SymbolicAtoms : IReadOnlyCollection, IReadOnlyDictionary { #region Attributes @@ -145,7 +148,7 @@ public static implicit operator SymbolicAtoms(ClingoSymbolicAtoms clingoSymbolic /// The name of the signature /// The arity of the signature /// The sign of the signature - /// An + /// An of public IEnumerator BySignature(string name, int arity, bool positive = true) { Clingo.HandleClingoError(Symbol.GetSymbolModule().CreateSignature(name, Convert.ToUInt32(arity), positive, out ClingoSignature signature)); diff --git a/test.ps1 b/test.ps1 index 53677de..37fbc98 100644 --- a/test.ps1 +++ b/test.ps1 @@ -1,21 +1,24 @@ Write-Host "Clearing working directory..." -ForegroundColor Green -if (Test-Path ".\tests\bin\Debug\netcoreapp3.1\runtimes\win-x86\native\") +if (Test-Path ".\tests\bin\Debug\netcoreapp3.1\runtimes\win\native\") { - Write-Host "Deleting .\tests\bin\Debug\netcoreapp3.1\runtimes\win-x86\native\..." -ForegroundColor Yellow - Remove-Item ".\tests\bin\Debug\netcoreapp3.1\runtimes\win-x86\native\" -Recurse -ErrorAction Ignore + Write-Host "Deleting .\tests\bin\Debug\netcoreapp3.1\runtimes\win\native\..." -ForegroundColor Yellow + Remove-Item ".\tests\bin\Debug\netcoreapp3.1\runtimes\win\native\" -Recurse -ErrorAction Ignore } -if (Test-Path ".\tests\bin\Debug\netcoreapp3.1\runtimes\win-x64\native\") +if (Test-Path ".\tests\bin\Debug\netcoreapp3.1\files\") { - Write-Host "Deleting .\tests\bin\Debug\netcoreapp3.1\runtimes\win-x64\native\..." -ForegroundColor Yellow - Remove-Item ".\tests\bin\Debug\netcoreapp3.1\runtimes\win-x64\native\" -Recurse -ErrorAction Ignore + Write-Host "Deleting .\tests\bin\Debug\netcoreapp3.1\files\..." -ForegroundColor Yellow + Remove-Item ".\tests\bin\Debug\netcoreapp3.1\files\" -Recurse -ErrorAction Ignore } Write-Host "Copying clingo dependencies..." -ForegroundColor Green -Copy-Item ".\clingo\build\win\x86\bin\Release" ".\tests\bin\Debug\netcoreapp3.1\runtimes\win-x86\native\" -Recurse -Copy-Item ".\clingo\build\win\x64\bin\Release" ".\tests\bin\Debug\netcoreapp3.1\runtimes\win-x64\native\" -Recurse +Copy-Item ".\clingo\build\win\bin\Release" ".\tests\bin\Debug\netcoreapp3.1\runtimes\win\native\" -Recurse + +Write-Host "Copying test files dependencies..." -ForegroundColor Green + +Copy-Item ".\tests\files" ".\tests\bin\Debug\netcoreapp3.1\files" -Recurse Write-Host "Executing tests..." -ForegroundColor Green diff --git a/tests/ClingoSharp.Test.csproj b/tests/ClingoSharp.Tests.csproj similarity index 100% rename from tests/ClingoSharp.Test.csproj rename to tests/ClingoSharp.Tests.csproj diff --git a/tests/ControlTests.cs b/tests/ControlTests.cs index 8166af1..aed75cf 100644 --- a/tests/ControlTests.cs +++ b/tests/ControlTests.cs @@ -1,4 +1,7 @@ using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.IO; namespace ClingoSharp.Tests { @@ -6,9 +9,28 @@ namespace ClingoSharp.Tests public class ControlTests { [Test] - public void NewControl() + public void LoadFile() { - Control control = new Control(); + using Control control = new Control(); + string filename = Path.Combine(TestContext.CurrentContext.TestDirectory, "files", "model_a.lp"); + control.Load(filename); + + var parts = new List>>() + { + new Tuple>("base", new List() {}), + }; + + control.Ground(parts); + + List models = new List(); + control.Solve(onModel: m => + { + models.Add(m.ToString()); + return true; + }); + + Assert.AreEqual(1, models.Count); + Assert.AreEqual("a", models[0]); } } } \ No newline at end of file diff --git a/tests/EnumerationTests.cs b/tests/EnumerationTests.cs new file mode 100644 index 0000000..722bd71 --- /dev/null +++ b/tests/EnumerationTests.cs @@ -0,0 +1,242 @@ +using ClingoSharp.Enums; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ClingoSharp.Tests +{ + [TestFixture] + class EnumerationTests + { + [Test] + public void MessageCode_GetNames_Test() + { + IEnumerable names = Enumeration.GetNames(); + string[] expectedValues = + { + "OperationUndefined", + "RuntimeError", + "AtomUndefined", + "FileIncluded", + "VariableUnbounded", + "GlobalVariable", + "Other" + }; + + CollectionAssert.AreEquivalent(expectedValues, names); + } + + [Test] + public void MessageCode_Values_Test() + { + IEnumerable values = Enumeration.GetValues(); + MessageCode[] expectedValues = + { + MessageCode.OperationUndefined, + MessageCode.RuntimeError, + MessageCode.AtomUndefined, + MessageCode.FileIncluded, + MessageCode.VariableUnbounded, + MessageCode.GlobalVariable, + MessageCode.Other + }; + + CollectionAssert.AreEquivalent(expectedValues, values); + } + + [Test] + public void MessageCode_Value_Tests() + { + MessageCode messageCode = Enumeration.GetValue(0); + Assert.AreEqual(MessageCode.OperationUndefined, messageCode); + + messageCode = Enumeration.GetValue(1); + Assert.AreEqual(MessageCode.RuntimeError, messageCode); + + messageCode = Enumeration.GetValue(2); + Assert.AreEqual(MessageCode.AtomUndefined, messageCode); + + messageCode = Enumeration.GetValue(3); + Assert.AreEqual(MessageCode.FileIncluded, messageCode); + + messageCode = Enumeration.GetValue(4); + Assert.AreEqual(MessageCode.VariableUnbounded, messageCode); + + messageCode = Enumeration.GetValue(5); + Assert.AreEqual(MessageCode.GlobalVariable, messageCode); + + messageCode = Enumeration.GetValue(6); + Assert.AreEqual(MessageCode.Other, messageCode); + + Assert.Throws(() => { Enumeration.GetValue(-1); }); + Assert.Throws(() => { Enumeration.GetValue(typeof(object), 0); }); + } + + [Test] + public void MessageCode_Parse_Test() + { + MessageCode messageCode = Enumeration.Parse("OperationUndefined", false); + Assert.AreEqual(MessageCode.OperationUndefined, messageCode); + + messageCode = Enumeration.Parse("runtimeError", true); + Assert.AreEqual(MessageCode.RuntimeError, messageCode); + + messageCode = Enumeration.Parse("AtomUndefined"); + Assert.AreEqual(MessageCode.AtomUndefined, messageCode); + + messageCode = Enumeration.Parse("FileIncluded", false); + Assert.AreEqual(MessageCode.FileIncluded, messageCode); + + messageCode = Enumeration.Parse("variableUnbounded", true); + Assert.AreEqual(MessageCode.VariableUnbounded, messageCode); + + messageCode = Enumeration.Parse("GlobalVariable"); + Assert.AreEqual(MessageCode.GlobalVariable, messageCode); + + messageCode = Enumeration.Parse("Other"); + Assert.AreEqual(MessageCode.Other, messageCode); + + Assert.Throws(() => { Enumeration.Parse(null); }); + Assert.Throws(() => { Enumeration.Parse(typeof(MessageCode), " "); }); + Assert.Throws(() => { Enumeration.Parse("other"); }); + Assert.Throws(() => { Enumeration.Parse(typeof(object), "Error"); }); + } + + [Test] + public void ModelType_GetNames_Test() + { + IEnumerable names = Enumeration.GetNames(typeof(ModelType)); + string[] expectedValues = + { + "StableModel", + "BraveConsequences", + "CautiousConsequences" + }; + + CollectionAssert.AreEquivalent(expectedValues, names); + } + + [Test] + public void ModelType_Values_Test() + { + IEnumerable values = Enumeration.GetValues(typeof(ModelType)).Cast(); + ModelType[] expectedValues = + { + ModelType.StableModel, + ModelType.BraveConsequences, + ModelType.CautiousConsequences + }; + + CollectionAssert.AreEquivalent(expectedValues, values); + } + + [Test] + public void ModelType_Value_Tests() + { + ModelType modelType = (ModelType)Enumeration.GetValue(typeof(ModelType), 0); + Assert.AreEqual(ModelType.StableModel, modelType); + + modelType = (ModelType)Enumeration.GetValue(typeof(ModelType), 1); + Assert.AreEqual(ModelType.BraveConsequences, modelType); + + modelType = (ModelType)Enumeration.GetValue(typeof(ModelType), 2); + Assert.AreEqual(ModelType.CautiousConsequences, modelType); + + Assert.Throws(() => { Enumeration.GetValue(3); }); + } + + [Test] + public void ModelType_Parse_Test() + { + ModelType modelType = (ModelType)Enumeration.Parse(typeof(ModelType), "StableModel", false); + Assert.AreEqual(ModelType.StableModel, modelType); + + modelType = (ModelType)Enumeration.Parse(typeof(ModelType), "braveConsequenceS", true); + Assert.AreEqual(ModelType.BraveConsequences, modelType); + + modelType = (ModelType)Enumeration.Parse(typeof(ModelType), "CautiousConsequences"); + Assert.AreEqual(ModelType.CautiousConsequences, modelType); + + Assert.Throws(() => { Enumeration.Parse(typeof(ModelType), null); }); + Assert.Throws(() => { Enumeration.Parse(typeof(ModelType), " "); }); + Assert.Throws(() => { Enumeration.Parse(typeof(ModelType), "stableModel"); }); + } + + [Test] + public void SymbolType_GetNames_Test() + { + IEnumerable names = Enumeration.GetNames(typeof(SymbolType)); + string[] expectedValues = + { + "Infimum", + "Number", + "String", + "Function", + "Supremum" + }; + + CollectionAssert.AreEquivalent(expectedValues, names); + } + + [Test] + public void SymbolType_Values_Test() + { + IEnumerable values = Enumeration.GetValues(typeof(SymbolType)).Cast(); + SymbolType[] expectedValues = + { + SymbolType.Infimum, + SymbolType.Number, + SymbolType.String, + SymbolType.Function, + SymbolType.Supremum + }; + + CollectionAssert.AreEquivalent(expectedValues, values); + } + + [Test] + public void SymbolType_Value_Tests() + { + SymbolType symbolType = (SymbolType)Enumeration.GetValue(typeof(SymbolType), 0); + Assert.AreEqual(SymbolType.Infimum, symbolType); + + symbolType = (SymbolType)Enumeration.GetValue(typeof(SymbolType), 1); + Assert.AreEqual(SymbolType.Number, symbolType); + + symbolType = (SymbolType)Enumeration.GetValue(typeof(SymbolType), 2); + Assert.AreEqual(SymbolType.String, symbolType); + + symbolType = (SymbolType)Enumeration.GetValue(typeof(SymbolType), 3); + Assert.AreEqual(SymbolType.Function, symbolType); + + symbolType = (SymbolType)Enumeration.GetValue(typeof(SymbolType), 4); + Assert.AreEqual(SymbolType.Supremum, symbolType); + + Assert.Throws(() => { Enumeration.GetValue(5); }); + } + + [Test] + public void SymbolType_Parse_Test() + { + SymbolType symbolType = (SymbolType)Enumeration.Parse(typeof(SymbolType), "Infimum", false); + Assert.AreEqual(SymbolType.Infimum, symbolType); + + symbolType = (SymbolType)Enumeration.Parse(typeof(SymbolType), "number", true); + Assert.AreEqual(SymbolType.Number, symbolType); + + symbolType = (SymbolType)Enumeration.Parse(typeof(SymbolType), "String"); + Assert.AreEqual(SymbolType.String, symbolType); + + symbolType = Enumeration.Parse("Function"); + Assert.AreEqual(SymbolType.Function, symbolType); + + symbolType = Enumeration.Parse("supremum", true); + Assert.AreEqual(SymbolType.Supremum, symbolType); + + Assert.Throws(() => { Enumeration.Parse(typeof(SymbolType), null); }); + Assert.Throws(() => { Enumeration.Parse(typeof(SymbolType), " "); }); + Assert.Throws(() => { Enumeration.Parse(typeof(SymbolType), "infimun"); }); + } + } +} diff --git a/tests/files/model_a.lp b/tests/files/model_a.lp new file mode 100644 index 0000000..2c88a88 --- /dev/null +++ b/tests/files/model_a.lp @@ -0,0 +1 @@ +a.