From 17f6a9b9563f30a05040cc543ff701d5d75786e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=97=D0=B5=D0=BC=D0=BB=D1=8F=D0=BA?= <92867056+AlexanderZemlyak@users.noreply.github.com> Date: Sun, 21 Dec 2025 21:11:52 +0300 Subject: [PATCH] Spython test suite (#3362) * Reorganize files in TestSuite dir for multiple languages * Add SPython samples to TestSuite * Update TestRunner to support multiple languages * Delete dll files accidentally pushed * Update .gitignore * Revert "Delete dll files accidentally pushed" This reverts commit 62bcba2b821d58ae51ec98e9dadcf621bb0fc003. * Update testing dir path in Testing.cs * Improve TestRunner output * Add random module and it's usage sample * Reorganize gitignore files * Move pascal tests back to TestSuite and create new TestSuiteLanguagePlugins folder for SPython * Revert "Update testing dir path in Testing.cs" This reverts commit 7d94eafb25292421bce8315520b4f6a0de001bbd. * Revert crlf changes in pascal tests * Test changes of _RebuildReleaseAndRunTestsForGitHubActions.bat * Revert "Test changes of _RebuildReleaseAndRunTestsForGitHubActions.bat" This reverts commit 234ceae3e3a339fbc68a6170e2bd201dab14d67d. * Test changes in StorageLocationPicker * Another test changes in StorageLocationPicker.cs * Rename LanguagePlugins folder to AdditionalLanguages * Decouple TestRunner from language names and parameters * Revert calling TestRunner without parameters in .bat files * Fix formatter tests nogui exception handling * Small refactoring in Testing.cs and TestRunner fix of working directory --- .gitignore | 3 - .../Properties/AssemblyInfo.cs | 0 .../SPythonLanguageInfo/SPythonLanguage.cs | 0 .../SPythonLanguageInfo.csproj | 0 .../SPythonLanguageInformation.cs | 2 + .../SPythonParserKrylovMovchan/Errors.cs | 0 .../IndentArranger.cs | 0 .../SPythonParserKrylovMovchan/Keywords.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../SPythonLexer.cs | 0 .../SPythonLexer.lex | 0 .../SPythonParser.cs | 0 .../SPythonParser.csproj | 0 .../SPythonParser.y | 0 .../SPythonParserTools.cs | 0 .../SPythonParserYacc.cs | 0 .../SPythonParserKrylovMovchan/_ReBuild.bat | 0 .../generateParser.bat | 0 .../SPythonSyntaxTreeVisitor/Errors.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../SPythonSyntaxTreeVisitor.csproj | 0 .../spython_syntax_tree_visitor.cs | 0 .../AddForwardDeclarationsVisitor.cs | 0 .../AssignmentCharAsStringVisitor.cs | 0 .../BitwiseAssignmentDesugarVisitor.cs | 0 .../CompoundComparisonDesugarVisitor.cs | 0 .../EraseSpythonOnlyNodesVisitor.cs | 0 .../FindFunctionsNamesVisitor.cs | 0 ...ctionsWithNamedParametersDesugarVisitor.cs | 0 .../GeneratorObjectDesugarVisitor.cs | 0 .../ImportToUsesVisitor.cs | 0 .../KwargsFunctionDesugarVisitor.cs | 0 .../MapDesugarVisitor.cs | 0 .../NameCorrectVisitor.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../RetainUsedGlobalVariablesVisitor.cs | 0 .../ReturnDesugarVisitor.cs | 0 .../SPythonStandardTreeConverter.csproj | 0 .../StandardSyntaxTreeConverter.cs | 0 .../StringResources.cs | 0 .../SymbolTableFillingVisitor.cs | 0 .../TreeNodesRearrangementVisitor.cs | 0 .../TypeCorrectVisitor.cs | 0 .../UnsupportedConstructsVisitor.cs | 0 CodeCompletion/Testing.cs | 20 +- .../ParserTools/BaseLanguageInformation.cs | 2 + .../ParserTools/ILanguageInformation.cs | 2 + .../PascalABCLanguageInformation.cs | 2 + PascalABCNET.sln | 10 +- PascalABCNETLinux.sln | 10 +- TestSuite/.gitignore | 15 +- TestSuite/testsettings.config | 1 + TestSuiteAdditionalLanguages/.gitignore | 14 ++ .../GraphWPF_use_example.pys | 10 + .../CompilationSamples/IntFloatTest.pys | 8 + .../CompilationSamples/SPythonSystemPys.pys | 18 ++ .../CompilationSamples/argmin.pys | 18 ++ .../CompilationSamples/big_program.pys | 12 + .../compound_conditions_example.pys | 27 +++ .../CompilationSamples/delete_by_mouse.pys | 42 ++++ .../CompilationSamples/game_example.pys | 26 ++ .../CompilationSamples/global.pys | 1 + .../CompilationSamples/global_test.pys | 17 ++ .../CompilationSamples/global_var.pys | 8 + .../global_var_in_inner_block.pys | 3 + .../CompilationSamples/in_out_example.pys | 24 ++ .../CompilationSamples/itertools.pys | 32 +++ .../CompilationSamples/list_test.pys | 10 + .../CompilationSamples/list_use_example.pys | 13 + .../SPythonTests/CompilationSamples/math.pys | 99 ++++++++ .../CompilationSamples/mergesort.pys | 11 + .../SPythonTests/CompilationSamples/new.pys | 9 + .../primes_and_divisors.pys | 16 ++ .../CompilationSamples/print_tests.pys | 10 + .../CompilationSamples/random1.pys | 8 + .../CompilationSamples/set_example.pys | 11 + .../SPythonTests/CompilationSamples/str.pys | 5 + .../CompilationSamples/super_proga1.pys | 14 ++ .../CompilationSamples/super_proga2.pys | 11 + .../time_measurement_example.pys | 16 ++ .../CompilationSamples/unit_example.pys | 18 ++ .../CompilationSamples/unit_use_example.pys | 19 ++ .../SPythonTests/errors/error_global1.pys | 13 + .../SPythonTests/errors/global_var_error1.pys | 6 + .../SPythonTests/testsettings.config | 1 + _GenerateAllSetups.bat | 25 +- _RebuildReleaseAndRunTests.bat | 26 +- _RebuildReleaseAndRunTests.sh | 8 +- ...uildReleaseAndRunTestsForGitHubActions.bat | 29 ++- bin/Lib/random1.pys | 8 + bin/TestRunner.exe | Bin 71680 -> 77824 bytes bin/TestRunner.pas | 227 +++++++++++++----- .../Integrating new language.md | 2 +- pabcnetc.sln | 10 +- 94 files changed, 824 insertions(+), 128 deletions(-) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonLanguageInfo/Properties/AssemblyInfo.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonLanguageInfo/SPythonLanguage.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonLanguageInfo/SPythonLanguageInfo.csproj (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs (99%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/Errors.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/IndentArranger.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/Keywords.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/Properties/AssemblyInfo.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/SPythonLexer.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/SPythonLexer.lex (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/SPythonParser.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/SPythonParser.csproj (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/SPythonParser.y (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/SPythonParserTools.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/_ReBuild.bat (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SPythonParserKrylovMovchan/generateParser.bat (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Errors.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Properties/AssemblyInfo.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/SPythonSyntaxTreeVisitor.csproj (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/spython_syntax_tree_visitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AddForwardDeclarationsVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AssignmentCharAsStringVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/BitwiseAssignmentDesugarVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/CompoundComparisonDesugarVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/EraseSpythonOnlyNodesVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FindFunctionsNamesVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FunctionsWithNamedParametersDesugarVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/GeneratorObjectDesugarVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ImportToUsesVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/KwargsFunctionDesugarVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/MapDesugarVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/NameCorrectVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/Properties/AssemblyInfo.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/RetainUsedGlobalVariablesVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ReturnDesugarVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SPythonStandardTreeConverter.csproj (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StandardSyntaxTreeConverter.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StringResources.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SymbolTableFillingVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TreeNodesRearrangementVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TypeCorrectVisitor.cs (100%) rename {LanguagePlugins => AdditionalLanguages}/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/UnsupportedConstructsVisitor.cs (100%) create mode 100644 TestSuite/testsettings.config create mode 100644 TestSuiteAdditionalLanguages/.gitignore create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/GraphWPF_use_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/IntFloatTest.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/SPythonSystemPys.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/argmin.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/big_program.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/compound_conditions_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/delete_by_mouse.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/game_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_test.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var_in_inner_block.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/in_out_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/itertools.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_test.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_use_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/math.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/mergesort.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/new.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/primes_and_divisors.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/print_tests.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/random1.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/set_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/str.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga1.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga2.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/time_measurement_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_use_example.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/errors/error_global1.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/errors/global_var_error1.pys create mode 100644 TestSuiteAdditionalLanguages/SPythonTests/testsettings.config create mode 100644 bin/Lib/random1.pys diff --git a/.gitignore b/.gitignore index 957ad7155..ab1ce1f4c 100644 --- a/.gitignore +++ b/.gitignore @@ -123,8 +123,6 @@ # Debug-only intellisense problems /bin/log.txt -/TestSuite/formatter_tests/output/log.txt - # Regenerated before being run by .bat @@ -136,7 +134,6 @@ # this is added to index at "/bin/lib" /ReleaseGenerators/nunit.framework.dll -/TestSuite/errors/nunit.framework.dll diff --git a/LanguagePlugins/SPython/SPythonLanguageInfo/Properties/AssemblyInfo.cs b/AdditionalLanguages/SPython/SPythonLanguageInfo/Properties/AssemblyInfo.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonLanguageInfo/Properties/AssemblyInfo.cs rename to AdditionalLanguages/SPython/SPythonLanguageInfo/Properties/AssemblyInfo.cs diff --git a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguage.cs b/AdditionalLanguages/SPython/SPythonLanguageInfo/SPythonLanguage.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguage.cs rename to AdditionalLanguages/SPython/SPythonLanguageInfo/SPythonLanguage.cs diff --git a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInfo.csproj b/AdditionalLanguages/SPython/SPythonLanguageInfo/SPythonLanguageInfo.csproj similarity index 100% rename from LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInfo.csproj rename to AdditionalLanguages/SPython/SPythonLanguageInfo/SPythonLanguageInfo.csproj diff --git a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs b/AdditionalLanguages/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs similarity index 99% rename from LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs rename to AdditionalLanguages/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs index dc453f252..ff3ba20b8 100644 --- a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs +++ b/AdditionalLanguages/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs @@ -30,6 +30,8 @@ namespace Languages.SPython.Frontend.Data public override Dictionary ValidDirectives { get; protected set; } + public override string CommentSymbol => "#"; + public override string BodyStartBracket => null; public override string BodyEndBracket => null; diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/Errors.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/Errors.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/Errors.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/Errors.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/IndentArranger.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/IndentArranger.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/IndentArranger.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/IndentArranger.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/Keywords.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/Keywords.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/Keywords.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/Keywords.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/Properties/AssemblyInfo.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/Properties/AssemblyInfo.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/Properties/AssemblyInfo.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/Properties/AssemblyInfo.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonLexer.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonLexer.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonLexer.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonLexer.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonLexer.lex b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonLexer.lex similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonLexer.lex rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonLexer.lex diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParser.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParser.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.csproj b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParser.csproj similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.csproj rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParser.csproj diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.y b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParser.y similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.y rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParser.y diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserTools.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParserTools.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserTools.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParserTools.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/_ReBuild.bat b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/_ReBuild.bat similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/_ReBuild.bat rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/_ReBuild.bat diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/generateParser.bat b/AdditionalLanguages/SPython/SPythonParserKrylovMovchan/generateParser.bat similarity index 100% rename from LanguagePlugins/SPython/SPythonParserKrylovMovchan/generateParser.bat rename to AdditionalLanguages/SPython/SPythonParserKrylovMovchan/generateParser.bat diff --git a/LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Errors.cs b/AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Errors.cs similarity index 100% rename from LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Errors.cs rename to AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Errors.cs diff --git a/LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Properties/AssemblyInfo.cs b/AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Properties/AssemblyInfo.cs similarity index 100% rename from LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Properties/AssemblyInfo.cs rename to AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/Properties/AssemblyInfo.cs diff --git a/LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/SPythonSyntaxTreeVisitor.csproj b/AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/SPythonSyntaxTreeVisitor.csproj similarity index 100% rename from LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/SPythonSyntaxTreeVisitor.csproj rename to AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/SPythonSyntaxTreeVisitor.csproj diff --git a/LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/spython_syntax_tree_visitor.cs b/AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/spython_syntax_tree_visitor.cs similarity index 100% rename from LanguagePlugins/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/spython_syntax_tree_visitor.cs rename to AdditionalLanguages/SPython/SemanticAnalyzers/SPythonSyntaxTreeVisitor/spython_syntax_tree_visitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AddForwardDeclarationsVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AddForwardDeclarationsVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AddForwardDeclarationsVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AddForwardDeclarationsVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AssignmentCharAsStringVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AssignmentCharAsStringVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AssignmentCharAsStringVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/AssignmentCharAsStringVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/BitwiseAssignmentDesugarVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/BitwiseAssignmentDesugarVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/BitwiseAssignmentDesugarVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/BitwiseAssignmentDesugarVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/CompoundComparisonDesugarVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/CompoundComparisonDesugarVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/CompoundComparisonDesugarVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/CompoundComparisonDesugarVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/EraseSpythonOnlyNodesVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/EraseSpythonOnlyNodesVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/EraseSpythonOnlyNodesVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/EraseSpythonOnlyNodesVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FindFunctionsNamesVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FindFunctionsNamesVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FindFunctionsNamesVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FindFunctionsNamesVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FunctionsWithNamedParametersDesugarVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FunctionsWithNamedParametersDesugarVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FunctionsWithNamedParametersDesugarVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/FunctionsWithNamedParametersDesugarVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/GeneratorObjectDesugarVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/GeneratorObjectDesugarVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/GeneratorObjectDesugarVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/GeneratorObjectDesugarVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ImportToUsesVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ImportToUsesVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ImportToUsesVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ImportToUsesVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/KwargsFunctionDesugarVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/KwargsFunctionDesugarVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/KwargsFunctionDesugarVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/KwargsFunctionDesugarVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/MapDesugarVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/MapDesugarVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/MapDesugarVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/MapDesugarVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/NameCorrectVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/NameCorrectVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/NameCorrectVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/NameCorrectVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/Properties/AssemblyInfo.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/Properties/AssemblyInfo.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/Properties/AssemblyInfo.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/Properties/AssemblyInfo.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/RetainUsedGlobalVariablesVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/RetainUsedGlobalVariablesVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/RetainUsedGlobalVariablesVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/RetainUsedGlobalVariablesVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ReturnDesugarVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ReturnDesugarVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ReturnDesugarVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/ReturnDesugarVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SPythonStandardTreeConverter.csproj b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SPythonStandardTreeConverter.csproj similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SPythonStandardTreeConverter.csproj rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SPythonStandardTreeConverter.csproj diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StandardSyntaxTreeConverter.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StandardSyntaxTreeConverter.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StandardSyntaxTreeConverter.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StandardSyntaxTreeConverter.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StringResources.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StringResources.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StringResources.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/StringResources.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SymbolTableFillingVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SymbolTableFillingVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SymbolTableFillingVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/SymbolTableFillingVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TreeNodesRearrangementVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TreeNodesRearrangementVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TreeNodesRearrangementVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TreeNodesRearrangementVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TypeCorrectVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TypeCorrectVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TypeCorrectVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/TypeCorrectVisitor.cs diff --git a/LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/UnsupportedConstructsVisitor.cs b/AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/UnsupportedConstructsVisitor.cs similarity index 100% rename from LanguagePlugins/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/UnsupportedConstructsVisitor.cs rename to AdditionalLanguages/SPython/SyntaxTreeConverters/SPythonStandardTreeConverter/UnsupportedConstructsVisitor.cs diff --git a/CodeCompletion/Testing.cs b/CodeCompletion/Testing.cs index ed5216926..bb66d6426 100644 --- a/CodeCompletion/Testing.cs +++ b/CodeCompletion/Testing.cs @@ -345,7 +345,7 @@ namespace CodeCompletion int col=0; PascalABCCompiler.Parsers.KeywordKind keyw; //LanguageIntegration.LanguageIntegrator.ReloadAllParsers(); - IParser parser = LanguageProvider.Instance.SelectLanguageByName(StringConstants.pascalLanguageName).Parser; + IParser parser = LanguageProvider.Instance.MainLanguage.Parser; string test_str = "System.Console"; off = test_str.Length; @@ -1093,25 +1093,27 @@ namespace CodeCompletion { var dir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName); var ind = dir.LastIndexOf("bin"); - return dir.Substring(0, ind) + "TestSuite"; + return Path.Combine(dir.Substring(0, ind - 1), "TestSuite"); } public static void Test() { - string test_dir = Path.Combine(GetTestSuiteDir(), @"formatter_tests"); - string output_dir = Path.Combine(test_dir, @"output"); + string test_dir = Path.Combine(GetTestSuiteDir(), "formatter_tests"); + string output_dir = Path.Combine(test_dir, "output"); Directory.CreateDirectory(output_dir); - string[] files = Directory.GetFiles(test_dir+@"\input","*.pas"); - StreamWriter log = new StreamWriter(Path.Combine(output_dir, @"log.txt"), false, Encoding.GetEncoding(1251)); + string[] files = Directory.GetFiles(Path.Combine(test_dir, "input"), "*.pas"); + StreamWriter log = new StreamWriter(Path.Combine(output_dir, "log.txt"), false, Encoding.GetEncoding(1251)); SyntaxTreeComparer stc = new SyntaxTreeComparer(); + + // Поддержка только PascalABC.NET пока + IParser parser = LanguageProvider.Instance.MainLanguage.Parser; + foreach (string s in files) { string Text = new StreamReader(s,System.Text.Encoding.GetEncoding(1251)).ReadToEnd(); List Errors = new List(); List Warnings = new List(); - IParser parser = LanguageProvider.Instance.SelectLanguageByExtension(s).Parser; - compilation_unit cu = parser.GetCompilationUnitForFormatter(s, Text, Errors, Warnings); if (Errors.Count == 0) { @@ -1151,7 +1153,7 @@ namespace CodeCompletion sr.Close(); List Errors = new List(); List Warnings = new List(); - compilation_unit cu = LanguageProvider.Instance.SelectLanguageByExtension(s).Parser.GetCompilationUnitForFormatter(s, Text, Errors, Warnings); + compilation_unit cu = parser.GetCompilationUnitForFormatter(s, Text, Errors, Warnings); CodeFormatters.CodeFormatter cf = new CodeFormatters.CodeFormatter(2); string Text2 = cf.FormatTree(Text, cu, 1, 1); if (Text.Replace("\r\n","\n") != Text2.Replace("\r\n","\n")) diff --git a/ParserTools/ParserTools/BaseLanguageInformation.cs b/ParserTools/ParserTools/BaseLanguageInformation.cs index d3d5d4c54..f62b9a3c4 100644 --- a/ParserTools/ParserTools/BaseLanguageInformation.cs +++ b/ParserTools/ParserTools/BaseLanguageInformation.cs @@ -26,6 +26,8 @@ namespace PascalABCCompiler.Parsers public abstract Dictionary ValidDirectives { get; protected set; } + public abstract string CommentSymbol { get; } + public abstract string BodyStartBracket { get; } public abstract string BodyEndBracket { get; } diff --git a/ParserTools/ParserTools/ILanguageInformation.cs b/ParserTools/ParserTools/ILanguageInformation.cs index 45f0195d9..9450ad933 100644 --- a/ParserTools/ParserTools/ILanguageInformation.cs +++ b/ParserTools/ParserTools/ILanguageInformation.cs @@ -192,6 +192,8 @@ namespace PascalABCCompiler.Parsers /// Dictionary ValidDirectives { get; } + string CommentSymbol { get; } + string BodyStartBracket { get; diff --git a/PascalABCLanguageInfo/PascalABCLanguageInformation.cs b/PascalABCLanguageInfo/PascalABCLanguageInformation.cs index 48b77d3c8..53c368c69 100644 --- a/PascalABCLanguageInfo/PascalABCLanguageInformation.cs +++ b/PascalABCLanguageInfo/PascalABCLanguageInformation.cs @@ -96,6 +96,8 @@ namespace Languages.Pascal.Frontend.Data #endregion } + public override string CommentSymbol => "//"; + public override string BodyStartBracket { get diff --git a/PascalABCNET.sln b/PascalABCNET.sln index ac6db69a3..ab2285ed3 100644 --- a/PascalABCNET.sln +++ b/PascalABCNET.sln @@ -59,7 +59,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Optimizer", "Optimizer\Opti EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeCompletion", "CodeCompletion\CodeCompletion.csproj", "{1AB15F6E-C22E-499A-A7ED-54BA7DE5CFA6}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LanguagePlugins", "LanguagePlugins", "{BB6973BA-B3A2-4B31-A986-7CB008F22C4F}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdditionalLanguages", "AdditionalLanguages", "{BB6973BA-B3A2-4B31-A986-7CB008F22C4F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Trees", "Trees", "{94EED2FF-0641-4562-8167-CBC280A733AF}" EndProject @@ -117,13 +117,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SPython", "SPython", "{C12F EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SyntaxTreeConverters", "SyntaxTreeConverters", "{E51C8CE6-9785-4666-9CD2-BADB728933E3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonSyntaxTreeVisitor", "LanguagePlugins\SPython\SemanticAnalyzers\SPythonSyntaxTreeVisitor\SPythonSyntaxTreeVisitor.csproj", "{D38A21E0-1D61-4905-82B3-1800E1991D57}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonSyntaxTreeVisitor", "AdditionalLanguages\SPython\SemanticAnalyzers\SPythonSyntaxTreeVisitor\SPythonSyntaxTreeVisitor.csproj", "{D38A21E0-1D61-4905-82B3-1800E1991D57}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonStandardTreeConverter", "LanguagePlugins\SPython\SyntaxTreeConverters\SPythonStandardTreeConverter\SPythonStandardTreeConverter.csproj", "{431AA1A0-81B9-4D93-9CB1-219BDF7825C9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonStandardTreeConverter", "AdditionalLanguages\SPython\SyntaxTreeConverters\SPythonStandardTreeConverter\SPythonStandardTreeConverter.csproj", "{431AA1A0-81B9-4D93-9CB1-219BDF7825C9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonParser", "LanguagePlugins\SPython\SPythonParserKrylovMovchan\SPythonParser.csproj", "{81FE2BAA-D100-4596-A392-F03BBE30F829}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonParser", "AdditionalLanguages\SPython\SPythonParserKrylovMovchan\SPythonParser.csproj", "{81FE2BAA-D100-4596-A392-F03BBE30F829}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonLanguageInfo", "LanguagePlugins\SPython\SPythonLanguageInfo\SPythonLanguageInfo.csproj", "{DFF88E9F-AFB3-4986-84FE-77F8A04CB6F0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonLanguageInfo", "AdditionalLanguages\SPython\SPythonLanguageInfo\SPythonLanguageInfo.csproj", "{DFF88E9F-AFB3-4986-84FE-77F8A04CB6F0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/PascalABCNETLinux.sln b/PascalABCNETLinux.sln index fcd9beb60..06dd6257c 100644 --- a/PascalABCNETLinux.sln +++ b/PascalABCNETLinux.sln @@ -63,7 +63,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LanguageIntegrator", "Langu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PascalABCLanguageInfo", "PascalABCLanguageInfo\PascalABCLanguageInfo.csproj", "{BD902586-E0D5-407A-904A-32249B8B709E}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LanguagePlugins", "LanguagePlugins", "{36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdditionalLanguages", "AdditionalLanguages", "{36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SPython", "SPython", "{D71D6350-AEE9-491F-A99E-9A2D00071020}" EndProject @@ -71,13 +71,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SemanticAnalyzers", "Semant EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SyntaxTreeConverters", "SyntaxTreeConverters", "{C4104880-9AC0-42F5-9962-D0C3FD143139}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonSyntaxTreeVisitor", "LanguagePlugins\SPython\SemanticAnalyzers\SPythonSyntaxTreeVisitor\SPythonSyntaxTreeVisitor.csproj", "{26DB8340-9A8F-16E1-6E6D-D59E97D05142}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonSyntaxTreeVisitor", "AdditionalLanguages\SPython\SemanticAnalyzers\SPythonSyntaxTreeVisitor\SPythonSyntaxTreeVisitor.csproj", "{26DB8340-9A8F-16E1-6E6D-D59E97D05142}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonLanguageInfo", "LanguagePlugins\SPython\SPythonLanguageInfo\SPythonLanguageInfo.csproj", "{15D55C2B-37A6-850E-D0CF-74C43CBB9E3F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonLanguageInfo", "AdditionalLanguages\SPython\SPythonLanguageInfo\SPythonLanguageInfo.csproj", "{15D55C2B-37A6-850E-D0CF-74C43CBB9E3F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonStandardTreeConverter", "LanguagePlugins\SPython\SyntaxTreeConverters\SPythonStandardTreeConverter\SPythonStandardTreeConverter.csproj", "{6883EC33-B9FD-6D48-B0C3-16F451552C9F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonStandardTreeConverter", "AdditionalLanguages\SPython\SyntaxTreeConverters\SPythonStandardTreeConverter\SPythonStandardTreeConverter.csproj", "{6883EC33-B9FD-6D48-B0C3-16F451552C9F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonParser", "LanguagePlugins\SPython\SPythonParserKrylovMovchan\SPythonParser.csproj", "{CEEEDB1E-B0E1-283E-13C3-BFE73FE8A446}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonParser", "AdditionalLanguages\SPython\SPythonParserKrylovMovchan\SPythonParser.csproj", "{CEEEDB1E-B0E1-283E-13C3-BFE73FE8A446}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/TestSuite/.gitignore b/TestSuite/.gitignore index a0f2c2bcb..cbfc22e5e 100644 --- a/TestSuite/.gitignore +++ b/TestSuite/.gitignore @@ -5,14 +5,15 @@ *.exe *.pdb *.xml -/exe/*.dll -/formatter_tests/output/**/*.pas +exe/*.dll +formatter_tests/output/**/*.pas +formatter_tests/output/log.txt +errors/nunit.framework.dll - -/exe/input.txt -/exe/out.txt -/exe/test.txt -/exe/*.dat +exe/input.txt +exe/out.txt +exe/test.txt +exe/*.dat diff --git a/TestSuite/testsettings.config b/TestSuite/testsettings.config new file mode 100644 index 000000000..face76016 --- /dev/null +++ b/TestSuite/testsettings.config @@ -0,0 +1 @@ +languageName: PascalABC.NET \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/.gitignore b/TestSuiteAdditionalLanguages/.gitignore new file mode 100644 index 000000000..94576a2ea --- /dev/null +++ b/TestSuiteAdditionalLanguages/.gitignore @@ -0,0 +1,14 @@ +# general ignore +*.exe +*.pdb +*.xml +*/exe/*.dll +*/formatter_tests/output/**/*.pas +*/formatter_tests/output/log.txt +*/errors/nunit.framework.dll + + +*/exe/input.txt +*/exe/out.txt +*/exe/test.txt +*/exe/*.dat \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/GraphWPF_use_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/GraphWPF_use_example.pys new file mode 100644 index 000000000..fd9d70def --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/GraphWPF_use_example.pys @@ -0,0 +1,10 @@ +from GraphWPF import * + +color = RandomColor() + +def MouseMove(x: float, y: float, mb: int): + if mb == 1: + FillCircle(x, y, 10, color) + + +OnMouseMove = MouseMove diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/IntFloatTest.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/IntFloatTest.pys new file mode 100644 index 000000000..a0c8bca01 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/IntFloatTest.pys @@ -0,0 +1,8 @@ +print(2) +print(0) +print(-0) +print(-2) +print(2.3) +print(2.) +print(.4) +print(-.2) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/SPythonSystemPys.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/SPythonSystemPys.pys new file mode 100644 index 000000000..7211115f9 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/SPythonSystemPys.pys @@ -0,0 +1,18 @@ +from PABCSystem import Object as obj, Write as pas_print +from SPythonSystem import range, len + +def print(*args: obj, **kwargs: str): + sep: str = ' ' + end: str = '\n' + if 'sep' in kwargs.get_keys(): + sep = kwargs['sep'] + if 'end' in kwargs.get_keys(): + end = kwargs['end'] + + for i in range(0, len(args) - 1): + pas_print(args[i]) + pas_print(sep) + + if len(args) != 0: + pas_print(args[len(args) - 1]) + pas_print(end) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/argmin.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/argmin.pys new file mode 100644 index 000000000..eb142e0ae --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/argmin.pys @@ -0,0 +1,18 @@ +# индекс минимального элемента +def argmin(arr: list[int]) -> int: + if len(arr) == 0: + return -1 + res = 0 + for i in range(1, len(arr)): + if arr[i] < arr[res]: + res = i + return res + + + + +print(argmin([1, 2, 3])) +print(argmin([3, 2, 1])) +# a = [4,9,16,8,2,15,13,13,15,2,8,16,9,4] +a = [i ** 2 % 17 for i in range(2, 16)] +print(argmin([i ** 2 % 17 for i in range(2, 16)])) diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/big_program.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/big_program.pys new file mode 100644 index 000000000..23dbb906c --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/big_program.pys @@ -0,0 +1,12 @@ +a = 2 +a = 3 +b = 1 + a +print(b) + +if True: + c = 23 + + + +def f(): + print(a) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/compound_conditions_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/compound_conditions_example.pys new file mode 100644 index 000000000..20332be55 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/compound_conditions_example.pys @@ -0,0 +1,27 @@ +N = 7 + +# Выводит первые N чисел, +# которые можно тремя различными +# способами представить как +# сумму двух квадратов целых чисел +def print_sequence(N: int): + a = 0 + while True: + a += 1 + for b in range(1, a): + for c in range(1, b): + for d in range(1, c + 1): + for e in range(1, d): + for f in range(1, e): + if a ** 2 + f ** 2 == b ** 2 + e ** 2 == c ** 2 + d ** 2: + print(a ** 2 + f ** 2, '\t= ', + a, '^2 + ', f, '^2 \t= ', + b, '^2 + ', e, '^2 \t= ', + c, '^2 + ', d, '^2', sep='') + + N -= 1 + if N == 0: + return + + +print_sequence(N) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/delete_by_mouse.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/delete_by_mouse.pys new file mode 100644 index 000000000..1a0c29675 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/delete_by_mouse.pys @@ -0,0 +1,42 @@ +from WPFObjects import RectangleWPF, ObjectUnderPoint +from WPFObjects import Colors, Window, OnMouseDown +from PABCSystem import Random, Inc, Milliseconds + +CountSquares = 10 +StatusRect: RectangleWPF +CurrentDigit = 1 +Mistakes = 0 + +def DrawStatusText(): + if CurrentDigit <= CountSquares: + StatusRect.Text = ('Удалено квадратов: ' + str(CurrentDigit-1) + + '\tОшибок: ' + str(Mistakes)) + else: + StatusRect.Text = ('Игра окончена. Время: ' + str(Milliseconds() // 1000) + + ' с.\tОшибок: ' + str(Mistakes)) + + +def MyMouseDown(x: float, y: float, mb: int): + ob = ObjectUnderPoint(x, y) + if ob is RectangleWPF and ob != StatusRect: + if ob.Number == CurrentDigit: + ob.Destroy() + Inc(CurrentDigit) + DrawStatusText() + else: + ob.Color = Colors.Red + Inc(Mistakes) + DrawStatusText() + + +Window.Title = 'Игра: удали все квадраты по порядку' +for i in range(1, CountSquares + 1): + x = Random(Window.Width - 50) + y = Random(Window.Height - 100) + ob = new RectangleWPF(x, y, 50, 50, Colors.LightGreen, 1) + ob.FontSize = 25 + ob.Number = i +StatusRect = new RectangleWPF(0, Window.Height - 40, + Window.Width, 40, Colors.LightBlue) +DrawStatusText() +OnMouseDown = MyMouseDown \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/game_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/game_example.pys new file mode 100644 index 000000000..12f30b832 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/game_example.pys @@ -0,0 +1,26 @@ +import random as rnd + +hidden_number = rnd.randint(1, 100) +print('Угадай число от 1 до 100') +attempts = 0 +left_border = 1 +right_border = 100 +while True: + attempts += 1 + guess = int(input('Попытка ' + str(attempts) + ':')) + if guess < left_border or right_border < guess: + print('Число', guess, 'не из диапазона', + '[' + str(left_border) + ',', str(right_border) + ']') + continue + if guess < hidden_number: + left_border = guess + 1 + print('Загаданное число больше', guess); + elif guess > hidden_number: + right_border = guess - 1 + print('Загаданное число меньше', guess); + else: + print('Победа!!!') + break + print('Попробуй число от', left_border, + 'до', right_border) +print('Тебе понадобилось', attempts, 'попыток') \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global.pys new file mode 100644 index 000000000..f1a72fce1 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global.pys @@ -0,0 +1 @@ +print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, end='#', sep='!') \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_test.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_test.pys new file mode 100644 index 000000000..76339572a --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_test.pys @@ -0,0 +1,17 @@ +a = 10 + +def f(): + global a + a = 2 + print(a) + + +print(a) +f() +print(a) +if True: + print(a) + a = 3 + print(a) + +print(a) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var.pys new file mode 100644 index 000000000..a831f81dd --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var.pys @@ -0,0 +1,8 @@ +if True: + a = '123' + +a = 1 + + +def f(): + print(a) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var_in_inner_block.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var_in_inner_block.pys new file mode 100644 index 000000000..84ed188fd --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/global_var_in_inner_block.pys @@ -0,0 +1,3 @@ +if True: + a = '123' +a = 2 \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/in_out_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/in_out_example.pys new file mode 100644 index 000000000..c5bf877f2 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/in_out_example.pys @@ -0,0 +1,24 @@ +a = int(input('Введите первое число:')) +b = int(input('Введите второе число:')) + +def print_expressions(a: int, b: int): + print(a, ' +', b, '=', a + b, end = '\n') + print(a, ' -', b, '=', a - b, end = '\n') + print(a, ' *', b, '=', a * b, end = '\n') + print(a, ' %', b, '=', a % b, end = '\n') + print(a, ' /', b, '=', a / b, end = '\n') + print(a, '//', b, '=', a // b, end = '\n') + print(a, '**', b, '=', a ** b, end = '\n') + +print_expressions(a, b) + + +# Введите первое число: 10 +# Введите второе число: 6 +# 10 + 6 = 16 +# 10 - 6 = 4 +# 10 * 6 = 60 +# 10 % 6 = 4 +# 10 / 6 = 1.66666666666667 +# 10 // 6 = 1 +# 10 ** 6 = 1000000 diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/itertools.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/itertools.pys new file mode 100644 index 000000000..d741c53a2 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/itertools.pys @@ -0,0 +1,32 @@ +# объединяет списки целых в один +def chain(*args: list[int]) -> list[int]: + sz = 0 + for arg in args: + sz += len(arg) + + res = [0 for i in range(sz)] + i = 0 + for arg in args: + for j in range(len(arg)): + res[i] = arg[j] + i += 1 + return res + +# если вызвать как repeat(10, times=12) +def repeat(val: int, **kwargs: int) -> list[int]: + times = 1 + if 'times' in kwargs.get_keys(): + times = kwargs['times'] + return [val for i in range(times)] + +# если вызвать как repeat(10, 12) +def repeat(val: int, times: int) -> list[int]: + return repeat(val, times=times) + # можно просто так + # return [val for i in range(times)] + + +# просто функция, чтобы показать как итерироваться по kwargs +def print_int_kwargs(**kwargs: int): + for key, value in kwargs: + print(f'kwargs[{key}] = {value}') \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_test.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_test.pys new file mode 100644 index 000000000..247098f9a --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_test.pys @@ -0,0 +1,10 @@ +a = [2 * i + 1 for i in range(0, 10) if i % 3 == 0] +print(type(a)) +for i in a: + print(i, end=' ') + +print() +for i in range(len(a)): + print(i, a[i], sep=': ') + +print() \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_use_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_use_example.pys new file mode 100644 index 000000000..a00806436 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/list_use_example.pys @@ -0,0 +1,13 @@ +def print_matr(matr: list[list[int]]): + for row in matr: + for elem in row: + print(elem, '\t', end=' ') + print() + + +matrix_of_integers: list[list[int]] +matrix_of_integers = [ + [j * i for j in range(1, 10)] + for i in range(1, 10) if i % 2 == 0 + ] +print_matr(matrix_of_integers) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/math.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/math.pys new file mode 100644 index 000000000..99d6d8cce --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/math.pys @@ -0,0 +1,99 @@ +import PABCSystem + +pi = 3.14 + +def sqrt(x: float) -> float: + return PABCSystem.sqrt(x) + +def trunc(x: float) -> int: + return PABCSystem.trunc(x) + +def floor(x: float) -> int: + return PABCSystem.floor(x) + +def ceil(x: float) -> int: + return PABCSystem.ceil(x) + +def log(x: float) -> float: + return PABCSystem.Log(x) + +def log1p(x: float) -> float: + return PABCSystem.Log(1+ x) + +def log2(x: float) -> float: + return PABCSystem.Log2(x) + +def log10(x: float) -> float: + return PABCSystem.Log10(x) + +def log(x: float, base: int) -> float: + return PABCSystem.LogN(base, x) + +def exp(x: float) -> float: + return PABCSystem.exp(x) + +def expm1(x: float) -> float: + return PABCSystem.exp(x - 1) + +def exp2(x: float) -> float: + return PABCSystem.exp(log(2) * x) + +def sin(x: float) -> float: + return PABCSystem.sin(x) + +def sinh(x: float) -> float: + return PABCSystem.sinh(x) + +def cos(x: float) -> float: + return PABCSystem.cos(x) + +def cosh(x: float) -> float: + return PABCSystem.cosh(x) + +def tan(x: float) -> float: + return PABCSystem.tan(x) + +def tanh(x: float) -> float: + return PABCSystem.tanh(x) + +def acos(x: float) -> float: + return PABCSystem.arccos(x) + +def asin(x: float) -> float: + return PABCSystem.arcsin(x) + +def atan(x: float) -> float: + return PABCSystem.arctan(x) + +def atan2(y: float, x: float) -> float: + return PABCSystem.arctan(y / x) + +def pow(x: float, y: int) -> float: + return PABCSystem.power(x, y) + +def cbrt(x: float) -> float: + return pow(x, 1/3) + +def fabs(x: float) -> float: + return PABCSystem.abs(x) + +def pow(x: float, y: float) -> float: + return PABCSystem.power(x, y) + +def isqrt(x: int) -> int: + return floor(sqrt(x)) + +def remainder(x: int, y: int) -> int: + return x - (x // y) * y + +def factorial(n: int) -> int: + if n == 0: + return 1 + return n * factorial(n - 1) + +def perm(n: int, k: int) -> int: + return factorial(n) // factorial(n - k) + +def comb(n: int, k: int) -> int: + return perm(n, k) // factorial(k) + diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/mergesort.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/mergesort.pys new file mode 100644 index 000000000..7d908f445 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/mergesort.pys @@ -0,0 +1,11 @@ +import time +start = time.time() +bound = 100000 +primes = 0 +for i in range(2, bound): + divisors = i-1 + while i % divisors != 0: + divisors = divisors - 1 + if divisors == 1: + primes = primes + 1 +print(primes, time.time() - start) diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/new.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/new.pys new file mode 100644 index 000000000..dcd45a73c --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/new.pys @@ -0,0 +1,9 @@ +a = [1, 2, 3] +a.append(4) +a.insert(4, 2) +b = a.copy() +b.reverse() +print(b) +print(a) +print(a.count(2)) +print(a.pop(1)) diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/primes_and_divisors.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/primes_and_divisors.pys new file mode 100644 index 000000000..6453fad64 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/primes_and_divisors.pys @@ -0,0 +1,16 @@ +import time +primes = 0 +n = int(input()) +start = time.time() +divisors = 0 +for i in range(2, n): + divisors = i-1 + while i % divisors != 0: + divisors = divisors - 1 + if divisors == 1: + primes = primes + 1 +print(primes, time.time() - start) + + +#def f(): +# print(primes, n, start, divisors) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/print_tests.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/print_tests.pys new file mode 100644 index 000000000..453ac6941 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/print_tests.pys @@ -0,0 +1,10 @@ +print(1) +print(1, 2, 3) +print() +print(sep='#') +print(end='!\n') +print(sep='#', end='!\n') +print(end='!\n', sep='#') +print(1, sep='#', end='!\n') +print(1, 2, 3, sep='#', end='!\n') +#print(1, sep='$', 2) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/random1.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/random1.pys new file mode 100644 index 000000000..d7e159ad4 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/random1.pys @@ -0,0 +1,8 @@ +#unit random +import PABCSystem + +def random() -> float: + return PABCSystem.random() + +def randint(a: int, b: int) -> int: + return PABCSystem.random(a, b) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/set_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/set_example.pys new file mode 100644 index 000000000..575d1c54f --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/set_example.pys @@ -0,0 +1,11 @@ +from time import time + +s: set[int] = set() +t1 = time() + +for i in range(1, 10000): + s |= {i} + +t2 = time() +print(t2 - t1) +print(len(s)) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/str.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/str.pys new file mode 100644 index 000000000..612ab8dfc --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/str.pys @@ -0,0 +1,5 @@ +s = '123#4\'#\'' #1212 +s.IndexOf('3').print() #12121 +print(s) #1212 +if True: + print(2) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga1.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga1.pys new file mode 100644 index 000000000..ad8de209b --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga1.pys @@ -0,0 +1,14 @@ +import random +b = [random.randint(0, 9) for i in range(20)] +b = [i for i in b if i % 2 == 0] +while True: + i = int(input()) + if 0 <= i and i < len(b): + print('your score is', b[i]) + break + elif i >= len(b): + print('try number less than', i) + elif i < 0: + print('try positive number like', 1) + else: + print('how is it even possible!?') diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga2.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga2.pys new file mode 100644 index 000000000..527477bbc --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/super_proga2.pys @@ -0,0 +1,11 @@ +def f(n: int) -> int: + if n == 0: + return 1 + return n + g(n - 1) +def g(n: int) -> int: + if n == 0: + return 0 + return n - f(n - 1) // 2 +for i in range(10): + print(i, ': ', f(i), ' ', g(i), sep='') + \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/time_measurement_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/time_measurement_example.pys new file mode 100644 index 000000000..fe054776e --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/time_measurement_example.pys @@ -0,0 +1,16 @@ +import time + +n = 60000 +start = time.time() +sm: float = 0 + +i = 1.0 +while i < n: + j = 1.0 + while j < n: + sm += 1.0 / i / j + j += 1 + i += 1 + +end = time.time(); +print(end - start) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_example.pys new file mode 100644 index 000000000..a70ba349b --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_example.pys @@ -0,0 +1,18 @@ +# Рекурсивная функция вычисления факториала +def factorial(n: int)-> bigint: + if n == 0: + return 1 + return n * factorial(n - 1) + + +# Не рекурсивная функция вычисления числа Фибоначчи +def fibonacci(n: int)-> bigint: + if n <= 1: + return n + f1: bigint = 0 + f2: bigint = 1 + for i in range(n - 1): + t = f1 + f2 + f1 = f2 + f2 = t + return f2 diff --git a/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_use_example.pys b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_use_example.pys new file mode 100644 index 000000000..87308e0eb --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/CompilationSamples/unit_use_example.pys @@ -0,0 +1,19 @@ +from unit_example import fibonacci as F, factorial as fact + +N = 10 + +fibs = [F(i) for i in range(1, N + 1)] +print("Последовательность чисел Фибоначчи:") +i = 0 +for fib_num in fibs: + i += 1 + print('F(' + str(i) + ')\t=', fib_num) +print() + +facts = [fact(i) for i in range(1, N + 1)] +print("Последовательность факториалов:") +i = 0 +for fact_num in facts: + i += 1 + print(str(i) + '!\t=', fact_num) +print() \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/errors/error_global1.pys b/TestSuiteAdditionalLanguages/SPythonTests/errors/error_global1.pys new file mode 100644 index 000000000..4f6eff7d5 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/errors/error_global1.pys @@ -0,0 +1,13 @@ +#!Имя 'a' присутствует в текущем пространстве имён +a = 10 +b = 2 + + +def f(a: int): + global a, b + b = 3 + print(a) + + +f(20) +print(b) \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/errors/global_var_error1.pys b/TestSuiteAdditionalLanguages/SPythonTests/errors/global_var_error1.pys new file mode 100644 index 000000000..aa5958a57 --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/errors/global_var_error1.pys @@ -0,0 +1,6 @@ +#!Неизвестное имя 'a' +def f(): + print(a) + +a = 1 +f() \ No newline at end of file diff --git a/TestSuiteAdditionalLanguages/SPythonTests/testsettings.config b/TestSuiteAdditionalLanguages/SPythonTests/testsettings.config new file mode 100644 index 000000000..e928b80ed --- /dev/null +++ b/TestSuiteAdditionalLanguages/SPythonTests/testsettings.config @@ -0,0 +1 @@ +languageName: SPython \ No newline at end of file diff --git a/_GenerateAllSetups.bat b/_GenerateAllSetups.bat index 023f69e00..e240f393e 100644 --- a/_GenerateAllSetups.bat +++ b/_GenerateAllSetups.bat @@ -38,15 +38,24 @@ ExecHide.exe gacutil.exe /i ..\bin\Lib\PABCRtl.dll @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -cd ..\bin -TestRunner.exe 1 -TestRunner.exe 2 -TestRunner.exe 3 -TestRunner.exe 4 -TestRunner.exe 5 -TestRunner.exe 6 +cd ..\TestSuite +..\bin\TestRunner.exe 1 +..\bin\TestRunner.exe 2 +..\bin\TestRunner.exe 3 +..\bin\TestRunner.exe 4 +..\bin\TestRunner.exe 5 +..\bin\TestRunner.exe 6 -cd ..\ReleaseGenerators +cd ..\TestSuiteAdditionalLanguages\SPythonTests +..\..\bin\TestRunner.exe 1 +..\..\bin\TestRunner.exe 2 +..\..\bin\TestRunner.exe 3 +..\..\bin\TestRunner.exe 4 +..\..\bin\TestRunner.exe 5 +..\..\bin\TestRunner.exe 6 + + +cd ..\..\ReleaseGenerators call PascalABCNET_ALL.bat GOTO EXIT diff --git a/_RebuildReleaseAndRunTests.bat b/_RebuildReleaseAndRunTests.bat index 32a646e47..722c5eec8 100644 --- a/_RebuildReleaseAndRunTests.bat +++ b/_RebuildReleaseAndRunTests.bat @@ -23,15 +23,23 @@ ExecHide.exe gacutil.exe /i ..\bin\Lib\PABCRtl.dll @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -cd ..\bin -REM MPGORunner.exe -TestRunner.exe 1 -TestRunner.exe 2 -TestRunner.exe 3 -TestRunner.exe 4 -TestRunner.exe 5 -TestRunner.exe 6 -cd .. +cd ..\TestSuite +REM ..\bin\MPGORunner.exe +..\bin\TestRunner.exe 1 +..\bin\TestRunner.exe 2 +..\bin\TestRunner.exe 3 +..\bin\TestRunner.exe 4 +..\bin\TestRunner.exe 5 +..\bin\TestRunner.exe 6 + +cd ..\TestSuiteAdditionalLanguages\SPythonTests +..\..\bin\TestRunner.exe 1 +..\..\bin\TestRunner.exe 2 +..\..\bin\TestRunner.exe 3 +..\..\bin\TestRunner.exe 4 +..\..\bin\TestRunner.exe 5 +..\..\bin\TestRunner.exe 6 +cd ..\.. GOTO EXIT diff --git a/_RebuildReleaseAndRunTests.sh b/_RebuildReleaseAndRunTests.sh index c4c146fdc..780f80f11 100644 --- a/_RebuildReleaseAndRunTests.sh +++ b/_RebuildReleaseAndRunTests.sh @@ -20,8 +20,10 @@ cd ReleaseGenerators mono ../bin/pabcnetc.exe RebuildStandartModulesMono.pas /rebuild if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then - cd ../bin - mono TestRunner.exe - cd .. + cd ../TestSuite + mono ../bin/TestRunner.exe + cd ../TestSuiteAdditionalLanguages/SPythonTests + mono ../../bin/TestRunner.exe + cd ../.. fi fi diff --git a/_RebuildReleaseAndRunTestsForGitHubActions.bat b/_RebuildReleaseAndRunTestsForGitHubActions.bat index e2b625417..eb6966692 100644 --- a/_RebuildReleaseAndRunTestsForGitHubActions.bat +++ b/_RebuildReleaseAndRunTestsForGitHubActions.bat @@ -23,21 +23,36 @@ ExecHide.exe gacutil.exe /i ..\bin\Lib\PABCRtl.dll @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -cd ..\bin +cd ..\TestSuite REM MPGORunner.exe -TestRunner.exe 1 1 +..\bin\TestRunner.exe 1 1 @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -TestRunner.exe 2 1 +..\bin\TestRunner.exe 2 1 @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -TestRunner.exe 3 1 +..\bin\TestRunner.exe 3 1 @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -TestRunner.exe 4 1 +..\bin\TestRunner.exe 4 1 @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -TestRunner.exe 5 1 +..\bin\TestRunner.exe 5 1 @IF %ERRORLEVEL% NEQ 0 GOTO ERROR -TestRunner.exe 6 1 +..\bin\TestRunner.exe 6 1 @IF %ERRORLEVEL% NEQ 0 GOTO ERROR +cd ..\TestSuiteAdditionalLanguages\SPythonTests +..\..\bin\TestRunner.exe 1 1 +@IF %ERRORLEVEL% NEQ 0 GOTO ERROR +..\..\bin\TestRunner.exe 2 1 +@IF %ERRORLEVEL% NEQ 0 GOTO ERROR +..\..\bin\TestRunner.exe 3 1 +@IF %ERRORLEVEL% NEQ 0 GOTO ERROR +..\..\bin\TestRunner.exe 4 1 +@IF %ERRORLEVEL% NEQ 0 GOTO ERROR +..\..\bin\TestRunner.exe 5 1 +@IF %ERRORLEVEL% NEQ 0 GOTO ERROR +..\..\bin\TestRunner.exe 6 1 +@IF %ERRORLEVEL% NEQ 0 GOTO ERROR + +cd ..\..\bin pabcnetcclear GitIgnoreTester.pas GitIgnoreTester.exe NoWait @IF %ERRORLEVEL% NEQ 0 GOTO ERROR diff --git a/bin/Lib/random1.pys b/bin/Lib/random1.pys new file mode 100644 index 000000000..d7e159ad4 --- /dev/null +++ b/bin/Lib/random1.pys @@ -0,0 +1,8 @@ +#unit random +import PABCSystem + +def random() -> float: + return PABCSystem.random() + +def randint(a: int, b: int) -> int: + return PABCSystem.random(a, b) \ No newline at end of file diff --git a/bin/TestRunner.exe b/bin/TestRunner.exe index b07aa5942d740aae60a56f68aad95e98227d0b27..94b4b2c70caafa1177567c9bbc325c83847e7f06 100644 GIT binary patch literal 77824 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 literal 71680 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 A(EtDd diff --git a/bin/TestRunner.pas b/bin/TestRunner.pas index 04774ec39..1983e1efd 100644 --- a/bin/TestRunner.pas +++ b/bin/TestRunner.pas @@ -10,10 +10,19 @@ uses PascalABCCompiler, System.IO, System.Diagnostics; +type + LanguageTestsInfo = auto class + + languageName: string; + languageExtensions: array of string; + commentSymbol: string; +end; + var TestSuiteDir: string; + CurrentLanguageInfo: LanguageTestsInfo; nogui: boolean; - + var PathSeparator: string := Path.DirectorySeparatorChar; @@ -22,11 +31,15 @@ begin Result := (System.Environment.OSVersion.Platform = System.PlatformID.Unix) or (System.Environment.OSVersion.Platform = System.PlatformID.MacOSX); end; -function GetTestSuiteDir: string; +function GetCurrentLanguageInfo(dir: string): LanguageTestsInfo; begin - var dir := Path.GetDirectoryName(GetEXEFileName()); - var ind := dir.LastIndexOf('bin'); - Result := dir.Substring(0, ind) + 'TestSuite'; + var configDict := &File.ReadLines(dir + PathSeparator + 'testsettings.config') + .Select(line -> line.Split([':', ' '], System.StringSplitOptions.RemoveEmptyEntries)) + .ToDictionary(arr -> arr[0], arr -> arr[1]); + + var languageInformation := Languages.Facade.LanguageProvider.Instance.SelectLanguageByName(configDict['languageName']).LanguageInformation; + + Result := new LanguageTestsInfo(languageInformation.Name, languageInformation.FilesExtensions, languageInformation.CommentSymbol); end; function GetLibDir: string; @@ -35,24 +48,37 @@ begin Result := dir + PathSeparator + 'Lib'; end; +function GetFilesByExtensions(path: string; extensions: array of string; searchOption: SearchOption := System.IO.SearchOption.TopDirectoryOnly): array of string; +begin + Result := extensions.SelectMany(ext -> Directory.GetFiles(path, $'*{ext}', searchOption)).ToArray(); +end; + +function GetCodeExamplesDir: string; +begin + var dir := Path.GetDirectoryName(GetEXEFileName()); + Result := (new DirectoryInfo(dir)).Parent.FullName + PathSeparator + 'CodeExamples' + PathSeparator + CurrentLanguageInfo.languageName; +end; + procedure CompileErrorTests(withide: boolean); begin + var dir := TestSuiteDir + PathSeparator + 'errors'; + if not Directory.Exists(dir) then exit; - - var files := Directory.GetFiles(TestSuiteDir + PathSeparator + 'errors', '*.pas'); + var commentSymbol := CurrentLanguageInfo.commentSymbol; + var files := GetFilesByExtensions(dir, CurrentLanguageInfo.languageExtensions); for var i := 0 to files.Length - 1 do begin var comp := new Compiler(); var content := &File.ReadAllText(files[i]); - if content.StartsWith('//winonly') and IsUnix then + if content.StartsWith(commentSymbol + 'winonly') and IsUnix then continue; - if content.StartsWith('//exclude') then + if content.StartsWith(commentSymbol + 'exclude') then continue; var errorMessage := ''; - if content.StartsWith('//!') then + if content.StartsWith(commentSymbol + '!') then begin - errorMessage := content.Substring(3, content.IndexOf(System.Environment.NewLine)-3).Trim; + errorMessage := content.Substring(commentSymbol.Length + 1, content.IndexOf(System.Environment.NewLine) - commentSymbol.Length + 1).Trim; end; var co: CompilerOptions := new CompilerOptions(files[i], CompilerOptions.OutputType.ConsoleApplicaton); co.Debug := true; @@ -78,11 +104,11 @@ begin raise new Exception('Compilation of ' + files[i] + ' failed' + System.Environment.NewLine + comp.ErrorsList[0].ToString()); System.Windows.Forms.MessageBox.Show('Compilation of ' + files[i] + ' failed' + System.Environment.NewLine + comp.ErrorsList[0].ToString()); end; - if (errorMessage <> '') and (comp.ErrorsList[comp.ErrorsList.Count-1].Message.Trim <> errorMessage) then + if (errorMessage <> '') and (comp.ErrorsList[comp.ErrorsList.Count - 1].Message.Trim <> errorMessage) then begin if nogui then - raise new Exception('Wrong error message in file ' + files[i] + ', should '+errorMessage+', is '+comp.ErrorsList[comp.ErrorsList.Count-1].Message); - System.Windows.Forms.MessageBox.Show('Wrong error message in file ' + files[i] + ', should '+errorMessage+', is '+comp.ErrorsList[comp.ErrorsList.Count-1].Message); + raise new Exception('Wrong error message in file ' + files[i] + ', should ' + errorMessage + ', is ' + comp.ErrorsList[comp.ErrorsList.Count - 1].Message); + System.Windows.Forms.MessageBox.Show('Wrong error message in file ' + files[i] + ', should ' + errorMessage + ', is ' + comp.ErrorsList[comp.ErrorsList.Count - 1].Message); end; end; if i mod 50 = 0 then @@ -96,15 +122,17 @@ begin var comp := new Compiler(); - var files := Directory.GetFiles(TestSuiteDir, '*.pas'); + var commentSymbol := CurrentLanguageInfo.commentSymbol; + var files := GetFilesByExtensions(TestSuiteDir, CurrentLanguageInfo.languageExtensions); + for var i := 0 to files.Length - 1 do begin if IsUnix then - writeln('Compile file '+files[i]); + Println('Compile file ' + files[i]); var content := &File.ReadAllText(files[i]); - if content.StartsWith('//winonly') and IsUnix then + if content.StartsWith(commentSymbol + 'winonly') and IsUnix then continue; - if content.StartsWith('//nopabcrtl') and withdll then + if content.StartsWith(commentSymbol + 'nopabcrtl') and withdll then continue; var co: CompilerOptions := new CompilerOptions(files[i], CompilerOptions.OutputType.ConsoleApplicaton); co.Debug := true; @@ -125,21 +153,21 @@ begin System.Windows.Forms.MessageBox.Show('Compilation of ' + files[i] + ' failed' + System.Environment.NewLine + comp.ErrorsList[0].ToString()); Halt(); end; - if content.StartsWith('//!') then + if content.StartsWith(commentSymbol + '!') then begin - var warning := content.Substring(3, content.IndexOf(System.Environment.NewLine)-3).Trim; + var warning := content.Substring(commentSymbol.Length + 1, content.IndexOf(System.Environment.NewLine) - commentSymbol.Length + 1).Trim; if comp.Warnings.Count = 0 then begin if nogui then - raise new Exception('Missing warning in '+files[i]); - System.Windows.Forms.MessageBox.Show('Missing warning in '+files[i]); + raise new Exception('Missing warning in ' + files[i]); + System.Windows.Forms.MessageBox.Show('Missing warning in ' + files[i]); Halt(); end; if comp.Warnings[0].Message <> warning then begin if nogui then - raise new Exception('Wrong warning for '+files[i]+': '+comp.Warnings[0].Message); - System.Windows.Forms.MessageBox.Show('Wrong warning for '+files[i]+': '+comp.Warnings[0].Message); + raise new Exception('Wrong warning for ' + files[i] + ': ' + comp.Warnings[0].Message); + System.Windows.Forms.MessageBox.Show('Wrong warning for ' + files[i] + ': ' + comp.Warnings[0].Message); Halt(); end; end; @@ -156,11 +184,15 @@ begin var comp := new Compiler(); - var files := Directory.GetFiles(TestSuiteDir + PathSeparator + dir, '*.pas'); + var fullDirName := TestSuiteDir + PathSeparator + dir; + if not Directory.Exists(fullDirName) then exit; + + var commentSymbol := CurrentLanguageInfo.commentSymbol; + var files := GetFilesByExtensions(fullDirName, CurrentLanguageInfo.languageExtensions); for var i := 0 to files.Length - 1 do begin var content := &File.ReadAllText(files[i]); - if content.StartsWith('//winonly') and IsUnix then + if content.StartsWith(commentSymbol + 'winonly') and IsUnix then continue; var co: CompilerOptions := new CompilerOptions(files[i], CompilerOptions.OutputType.ConsoleApplicaton); co.Debug := true; @@ -190,12 +222,16 @@ begin var comp := new Compiler(); // Не пропускать ошибки сохранения PCU, в тесте создания PCU comp.InternalDebug.SkipPCUErrors := false; - var files := Directory.GetFiles(TestSuiteDir + PathSeparator + 'units', '*.pas'); + var dir := TestSuiteDir + PathSeparator + 'units' + PathSeparator; + if not Directory.Exists(dir) then exit; + + var commentSymbol := CurrentLanguageInfo.commentSymbol; + var files := GetFilesByExtensions(TestSuiteDir + PathSeparator + 'units', CurrentLanguageInfo.languageExtensions); for var i := 0 to files.Length - 1 do begin var content := &File.ReadAllText(files[i]); - if content.StartsWith('//winonly') and IsUnix then + if content.StartsWith(commentSymbol + 'winonly') and IsUnix then continue; var co: CompilerOptions := new CompilerOptions(files[i], CompilerOptions.OutputType.ConsoleApplicaton); co.Debug := true; @@ -218,14 +254,18 @@ end; procedure CompileAllUsesUnits; begin - System.Environment.CurrentDirectory := Path.GetDirectoryName(GetEXEFileName()); var comp := new Compiler(); - var files := Directory.GetFiles(TestSuiteDir + PathSeparator + 'usesunits', '*.pas'); + var dir := TestSuiteDir + PathSeparator + 'usesunits'; + + if not Directory.Exists(dir) then exit; + + var commentSymbol := CurrentLanguageInfo.commentSymbol; + var files := GetFilesByExtensions(dir, CurrentLanguageInfo.languageExtensions); for var i := 0 to files.Length - 1 do begin var content := &File.ReadAllText(files[i]); - if content.StartsWith('//winonly') and IsUnix then + if content.StartsWith(commentSymbol + 'winonly') and IsUnix then continue; var co: CompilerOptions := new CompilerOptions(files[i], CompilerOptions.OutputType.ConsoleApplicaton); co.Debug := true; @@ -246,9 +286,11 @@ begin end; procedure CopyPCUFiles; -begin - System.Environment.CurrentDirectory := Path.GetDirectoryName(GetEXEFileName()); - var files := Directory.GetFiles(TestSuiteDir + PathSeparator + 'units', '*.pcu'); +begin + var dir := TestSuiteDir + PathSeparator + 'units'; + if not Directory.Exists(dir) then exit; + + var files := Directory.GetFiles(dir, '*.pcu'); foreach fname: string in files do begin @@ -263,7 +305,11 @@ begin begin System.IO.File.Copy(dll, TestSuiteDir + PathSeparator + 'exe' + PathSeparator + Path.GetFileName(dll), true); end; - var files := Directory.GetFiles(TestSuiteDir + PathSeparator + 'exe', '*.exe'); + + var dir := TestSuiteDir + PathSeparator + 'exe'; + if not Directory.Exists(dir) then exit; + + var files := Directory.GetFiles(dir, '*.exe'); for var i := 0 to files.Length - 1 do begin //Println(files[i]); @@ -282,7 +328,7 @@ begin p.StandardInput.WriteLine('GO'); //p.StandardInput.AutoFlush := true; //var p := System.Diagnostics.Process.Start(psi); - if nogui then + if nogui then begin var success := p.WaitForExit(60000); if not success then @@ -306,7 +352,9 @@ end; procedure RunExpressionsExtractTests; begin - CodeCompletion.CodeCompletionTester.Test(); + // Пока для других языков не поддерживается + if CurrentLanguageInfo.languageName <> 'PascalABC.NET' then exit; + CodeCompletion.CodeCompletionTester.Test(); end; function GetLineByPos(lines: array of string; pos: integer): integer; @@ -341,17 +389,27 @@ end; procedure RunIntellisenseTests; begin + var dir := TestSuiteDir + PathSeparator + 'intellisense_tests'; + if not Directory.Exists(dir) then exit; + PascalABCCompiler.StringResourcesLanguage.CurrentTwoLetterISO := 'ru'; - CodeCompletion.CodeCompletionTester.TestIntellisense(TestSuiteDir + PathSeparator + 'intellisense_tests'); + CodeCompletion.CodeCompletionTester.TestIntellisense(dir); end; procedure RunFormatterTests; begin + var dir := TestSuiteDir + PathSeparator + 'formatter_tests'; + if not Directory.Exists(dir) then exit; + CodeCompletion.FormatterTester.Test(); - var errors := &File.ReadAllText(TestSuiteDir + PathSeparator + 'formatter_tests' + PathSeparator + 'output' + PathSeparator + 'log.txt'); + var errors := &File.ReadAllText(dir + PathSeparator + 'output' + PathSeparator + 'log.txt'); if not string.IsNullOrEmpty(errors) then begin - System.Windows.Forms.MessageBox.Show(errors + System.Environment.NewLine + 'more info at TestSuite/formatter_tests/output/log.txt'); + var dirInfo := new DirectoryInfo(TestSuiteDir); + + if nogui then + raise new Exception('Formatter tests failed.' + NewLine + errors); + System.Windows.Forms.MessageBox.Show(errors + System.Environment.NewLine + $'more info at {dirInfo.Parent.Name}/{dirInfo.Name}/formatter_tests/output/log.txt'); Halt; end; end; @@ -388,82 +446,119 @@ begin ClearDirByPattern(TestSuiteDir + PathSeparator + 'usesunits', '*.pcu'); end; -procedure DeletePABCSystemPCU; -begin - var dir := Path.Combine(Path.GetDirectoryName(GetEXEFileName()), 'Lib'); - var pcu := Path.Combine(dir, 'PABCSystem.pcu'); -end; +//procedure DeletePABCSystemPCU; +//begin +// var dir := Path.Combine(Path.GetDirectoryName(GetEXEFileName()), 'Lib'); +// var pcu := Path.Combine(dir, 'PABCSystem.pcu'); +//end; procedure CopyLibFiles; begin - var files := Directory.GetFiles(GetLibDir(), '*.pas'); + var files := GetFilesByExtensions(GetLibDir(), CurrentLanguageInfo.languageExtensions); foreach f: string in files do begin &File.Copy(f, TestSuiteDir + PathSeparator + 'CompilationSamples' + PathSeparator + Path.GetFileName(f), true); end; end; +procedure CopyCodeExamples; +begin + var dir := GetCodeExamplesDir(); + if not Directory.Exists(dir) then exit; + + var files := GetFilesByExtensions(dir, CurrentLanguageInfo.languageExtensions, SearchOption.AllDirectories); + foreach f: string in files do + begin + &File.Copy(f, TestSuiteDir + PathSeparator + 'CompilationSamples' + PathSeparator + Path.GetFileName(f), true); + end; +end; + +function MsToMinutes(ms: integer) : string; +begin + var span := System.TimeSpan.FromMilliseconds(ms); + Result := span.Minutes > 0 ? $'{span.Minutes}m {span.Seconds}s' : $'{span.Seconds}s'; +end; + begin //DeletePABCSystemPCU; try Languages.Integration.LanguageIntegrator.LoadStandardLanguages(); - TestSuiteDir := GetTestSuiteDir; + TestSuiteDir := System.Environment.CurrentDirectory; + System.Environment.CurrentDirectory := Path.GetDirectoryName(GetEXEFileName()); + + CurrentLanguageInfo := GetCurrentLanguageInfo(TestSuiteDir); + + if (ParamCount = 0) or (ParamStr(1) = '1') then + Println($'----- {CurrentLanguageInfo.languageName} тесты -----'); + if (ParamCount = 2) and (ParamStr(2) = '1') then nogui := true; if (ParamCount = 0) or (ParamStr(1) = '1') then begin + Println('Compiling tests...'); DeletePCUFiles; ClearExeDir; CompileAllRunTests(false); - writeln('Tests to run: '+Milliseconds()+'ms'); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); end; if (ParamCount = 0) or (ParamStr(1) = '2') then begin + Println('Compiling compilation samples...'); CopyLibFiles; + CopyCodeExamples; CompileAllCompilationTests('CompilationSamples', false); - writeln('CompilationSamples: '+Milliseconds()+'ms'); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); end; if (ParamCount = 0) or (ParamStr(1) = '3') then begin + Println('Compiling tests with multiple units and error throwing tests...'); CompileAllUnits; CopyPCUFiles; CompileAllUsesUnits; CompileErrorTests(false); - writeln('Other tests '+Milliseconds()+'ms'+'. Tests compiled successfully '); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); end; if (ParamCount = 0) or (ParamStr(1) = '4') then begin + Println('Running tests...'); RunAllTests(false); - writeln('Tests run successfully: '+Milliseconds()+'ms'); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); ClearExeDir; DeletePCUFiles; end; if (ParamCount = 0) or (ParamStr(1) = '5') then begin - - CompileAllRunTests(false, true); - writeln('Tests in 32bit mode compiled successfully'); - RunAllTests(false); - writeln('Tests in 32bit run successfully'); - ClearExeDir; - CompileAllRunTests(true); - writeln('Tests with pabcrtl compiled successfully'); - CompileAllCompilationTests('pabcrtl_tests', true); + Println('Compiling tests in 32bit mode...'); + CompileAllRunTests(false, true); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); + Println('Running tests in 32bit mode...'); + RunAllTests(false); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); + ClearExeDir; + Println('Compiling tests with PABCRtl.dll...'); + CompileAllRunTests(true); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); + Println('Compiling compilation samples with PABCRtl.dll...'); + CompileAllCompilationTests('pabcrtl_tests', true); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); end; if (ParamCount = 0) or (ParamStr(1) = '6') then begin + Println('Running tests with PABCRtl.dll...'); RunAllTests(false); - writeln('Tests with pabcrtl run successfully'); - System.Environment.CurrentDirectory := Path.GetDirectoryName(GetEXEFileName()); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); + Println('Running intellisense expression tests...'); RunExpressionsExtractTests; - writeln('Intellisense expression tests run successfully'); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); + Println('Running basic intellisense tests...'); RunIntellisenseTests; - writeln('Intellisense tests run successfully'); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); + Println('Running formatter tests...'); RunFormatterTests; - writeln('Formatter tests run successfully'); + Println('Success. Time elapsed: ' + MsToMinutes(MillisecondsDelta())); end; except on e: Exception do @@ -472,6 +567,6 @@ begin raise new Exception(e.ToString()); assert(false, e.ToString()); end; - + end; end. \ No newline at end of file diff --git a/documentation/DeveloperGuides/Integrating new language.md b/documentation/DeveloperGuides/Integrating new language.md index ee2ad55b8..5f23669fb 100644 --- a/documentation/DeveloperGuides/Integrating new language.md +++ b/documentation/DeveloperGuides/Integrating new language.md @@ -1,5 +1,5 @@ ### Шаг 1 -Необходимо создать папку, называющуюся так же, как Ваш язык в папке *LanguagePlugins*, расположенной в корне репозитория. Далее создать в ней два обязательных проекта. Это проект парсера Вашего языка, а также проект, содержащий класс Вашего языка (унаследованный от класса `BaseLanguage`, находящегося в стандартном проекте `LanguageIntegrator`) и класс "базы данных" языка (унаследованный от класса `BaseLanguageInformation` из проекта `ParserTools`). +Необходимо создать папку, называющуюся так же, как Ваш язык в папке *AdditionalLanguages*, расположенной в корне репозитория. Далее создать в ней два обязательных проекта. Это проект парсера Вашего языка, а также проект, содержащий класс Вашего языка (унаследованный от класса `BaseLanguage`, находящегося в стандартном проекте `LanguageIntegrator`) и класс "базы данных" языка (унаследованный от класса `BaseLanguageInformation` из проекта `ParserTools`). Для совместимости целевой платформой Ваших проектов должна быть *.NET Framework 4.0*. В свойствах проекта и для Release, и для Debug версии должен быть выбран выходной путь `..\..\..\bin\`. diff --git a/pabcnetc.sln b/pabcnetc.sln index f2155001b..03cd36b41 100644 --- a/pabcnetc.sln +++ b/pabcnetc.sln @@ -53,7 +53,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StringConstants", "StringCo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LanguageIntegrator", "LanguageIntegrator\LanguageIntegrator.csproj", "{A48D9069-D569-4110-9252-A10F139B669B}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "LanguagePlugins", "LanguagePlugins", "{36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AdditionalLanguages", "AdditionalLanguages", "{36D591C7-65C7-A0D1-1CBC-10CDE441BDC8}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SPython", "SPython", "{DFCE8D21-EF89-4922-B662-65CF93E0F61B}" EndProject @@ -61,13 +61,13 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SemanticAnalyzers", "Semant EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SyntaxTreeConverters", "SyntaxTreeConverters", "{D7D9CC20-E09F-4FBC-8EEE-9FAB8406FCBB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonSyntaxTreeVisitor", "LanguagePlugins\SPython\SemanticAnalyzers\SPythonSyntaxTreeVisitor\SPythonSyntaxTreeVisitor.csproj", "{26DB8340-9A8F-16E1-6E6D-D59E97D05142}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonSyntaxTreeVisitor", "AdditionalLanguages\SPython\SemanticAnalyzers\SPythonSyntaxTreeVisitor\SPythonSyntaxTreeVisitor.csproj", "{26DB8340-9A8F-16E1-6E6D-D59E97D05142}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonStandardTreeConverter", "LanguagePlugins\SPython\SyntaxTreeConverters\SPythonStandardTreeConverter\SPythonStandardTreeConverter.csproj", "{6883EC33-B9FD-6D48-B0C3-16F451552C9F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonStandardTreeConverter", "AdditionalLanguages\SPython\SyntaxTreeConverters\SPythonStandardTreeConverter\SPythonStandardTreeConverter.csproj", "{6883EC33-B9FD-6D48-B0C3-16F451552C9F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonLanguageInfo", "LanguagePlugins\SPython\SPythonLanguageInfo\SPythonLanguageInfo.csproj", "{15D55C2B-37A6-850E-D0CF-74C43CBB9E3F}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonLanguageInfo", "AdditionalLanguages\SPython\SPythonLanguageInfo\SPythonLanguageInfo.csproj", "{15D55C2B-37A6-850E-D0CF-74C43CBB9E3F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonParser", "LanguagePlugins\SPython\SPythonParserKrylovMovchan\SPythonParser.csproj", "{CEEEDB1E-B0E1-283E-13C3-BFE73FE8A446}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SPythonParser", "AdditionalLanguages\SPython\SPythonParserKrylovMovchan\SPythonParser.csproj", "{CEEEDB1E-B0E1-283E-13C3-BFE73FE8A446}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution