diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml
index ea0b66d77..6dbadf7b4 100644
--- a/.github/workflows/sonar.yml
+++ b/.github/workflows/sonar.yml
@@ -11,7 +11,7 @@ jobs:
if: (github.repository == 'EvilBeaver/OneScript' ) && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.repository.full_name)
steps:
- name: Set up JDK 17
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
@@ -19,14 +19,14 @@ jobs:
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Cache SonarQube packages
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: ~\sonar\cache
key: ${{ runner.os }}-sonar
restore-keys: ${{ runner.os }}-sonar
- name: Cache SonarQube scanner
id: cache-sonar-scanner
- uses: actions/cache@v3
+ uses: actions/cache@v4
with:
path: .\.sonar\scanner
key: ${{ runner.os }}-sonar-scanner
diff --git a/Build.csproj b/Build.csproj
index d7273cda1..93eb134ab 100644
--- a/Build.csproj
+++ b/Build.csproj
@@ -1,27 +1,43 @@
-
-
- 1.1.0
+ 2.0.0
+
+ $(VersionPrefix)
+ $(VersionPrefix)-$(VersionSuffix)
+
$(BUILD_NUMBER)
0
$(MSBuildProjectDirectory)/built
- $(MSBuildProjectDirectory)/src/1Script.sln
+ $(ArtifactsRoot)/lib
+ $(ArtifactsRoot)\vscode\
Release
+ $(MSBuildProjectDirectory)/src/1Script.sln
+
x86
- bin32
+ Win32
- Any CPU
- bin
+ "Any CPU"
+ x64
-
+
+
+
+ oscript.csproj
+ net6.0
+
+
+ TestApp.csproj
+ net6.0-windows
+
+
+
@@ -29,219 +45,313 @@
-
+
-
-
-
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
- $(ArtifactsRoot)/tmp
- $(TempFolder)/lib
- $(TempFolder)/bin
- $(TempFolder)/examples
- $(TempFolder)/doc
- $(ArtifactsRoot)\vscode\
- $(ArtifactsRoot)/mddoc
+ $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration)
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
- $(TempFolder)/bin
-
-
- $(TempFolder)/bin32
-
+
+
+
+
+
+
+
+
+
+ $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration)
+
-
-
- $(TempFolder)/bin
-
-
- $(TempFolder)/bin32
-
+
+
-
-
-
-
-
- $(MSBuildProjectDirectory)/src/VSCode.DebugAdapter/bin/$(Configuration)/net461
-
+
+
+
-
-
-
-
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+ src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj
+ $(DebugAdapterDir)
+
-
-
-
-
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+ FirstItem = Items.First().ItemSpec;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ opm\src\cmd\opm.os
+ dotnet $(Runner) "$(LibDir)\$(OpmEntryPoint)"
+
+
-
+
+
+
+
+
+
-
+
+
+
-
-
+
-
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
-
-
+
+
+ $(MSBuildProjectDirectory)/src/Tests
+
-
-
-
-
+
+
+
+
-
+
+
+
+
+
+
+
+
+
-
-
-
-
- "$(InnoSetupPath)\iscc.exe"
- $(ArtifactsRoot)
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+ --version-suffix $(VersionSuffix)
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
-
+
+
+
+
-
-
+
+
-
+
diff --git a/Build_Core.csproj b/Build_Core.csproj
deleted file mode 100644
index 94e4a1c82..000000000
--- a/Build_Core.csproj
+++ /dev/null
@@ -1,356 +0,0 @@
-
-
- 2.0.0
-
- $(VersionPrefix)
- $(VersionPrefix)-$(VersionSuffix)
-
- $(BUILD_NUMBER)
- 0
-
- $(MSBuildProjectDirectory)/built
- $(ArtifactsRoot)/lib
- $(ArtifactsRoot)\vscode\
- Release
- $(MSBuildProjectDirectory)/src/1Script.sln
-
-
-
-
-
- x86
- Win32
-
-
- "Any CPU"
- x64
-
-
-
-
-
- oscript.csproj
- net6.0
-
-
- TestApp.csproj
- net6.0-windows
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(MSBuildProjectDirectory)/src/ScriptEngine.NativeApi/bin/$(Configuration)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj
- $(DebugAdapterDir)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- FirstItem = Items.First().ItemSpec;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- opm\src\cmd\opm.os
- dotnet $(Runner) "$(LibDir)\$(OpmEntryPoint)"
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- $(MSBuildProjectDirectory)/src/Tests
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- --version-suffix $(VersionSuffix)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Jenkinsfile b/Jenkinsfile
index 4213103b5..b2a3babc7 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -5,7 +5,7 @@ pipeline {
environment {
VersionPrefix = '2.0.0'
- VersionSuffix = 'rc3'
+ VersionSuffix = 'rc4'
outputEnc = '65001'
}
@@ -58,7 +58,7 @@ pipeline {
bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" src/1Script.sln /t:restore && mkdir doctool"
bat "chcp $outputEnc > nul\r\n dotnet publish src/OneScriptDocumenter/OneScriptDocumenter.csproj -c Release -o doctool"
- bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build_Core.csproj /t:CleanAll;PrepareDistributionFiles;CreateNuget"
+ bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build.csproj /t:CleanAll;PrepareDistributionFiles;CreateNuget"
stash includes: 'tests, built/**', name: 'buildResults'
}
@@ -126,7 +126,7 @@ pipeline {
deleteDir()
}
unstash 'buildResults'
- bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build_Core.csproj /t:Test"
+ bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build.csproj /t:Test"
junit 'tests/*.xml'
}
@@ -136,7 +136,7 @@ pipeline {
stage('Linux testing') {
agent{
docker {
- image 'mcr.microsoft.com/dotnet/sdk:5.0'
+ image 'mcr.microsoft.com/dotnet/sdk:6.0'
label 'linux'
}
}
@@ -187,16 +187,20 @@ pipeline {
unstash 'buildResults'
unstash 'nativeApiSo'
- bat 'xcopy output\\na-proxy\\*64.so built\\linux-64\\bin\\'
+ bat '''
+ chcp 65001 > nul
+ dir output\\na-proxy
+ xcopy output\\na-proxy\\*64.so built\\linux-x64\\bin\\ /F
+ '''.stripIndent()
script
{
if (env.BRANCH_NAME == "preview") {
echo 'Building preview'
- bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build_Core.csproj /t:PackDistributions /p:Suffix=-pre%BUILD_NUMBER%"
+ bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build.csproj /t:PackDistributions /p:Suffix=-pre%BUILD_NUMBER%"
}
else{
- bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build_Core.csproj /t:PackDistributions"
+ bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" Build.csproj /t:PackDistributions"
}
}
archiveArtifacts artifacts: 'built/**', fingerprint: true
@@ -213,7 +217,7 @@ pipeline {
agent { label 'master' }
steps {
-
+ cleanWs()
unstash 'dist'
unstash 'vsix'
diff --git a/README.md b/README.md
index 7737b5d62..25bf3d5c1 100644
--- a/README.md
+++ b/README.md
@@ -47,10 +47,57 @@ OneScript позволяет создавать и выполнять текст
- выполнить команду `mono ovm.exe use stable`
- перезапустить терминал
-Донастройка Self-Contained варианта поставки (не требующего инсталляции dotnet)
+#### Донастройка Self-Contained варианта поставки (не требующего инсталляции dotnet)
```
chmod +x ./oscript
xattr -d com.apple.quarantine *.dylib oscript
codesign -s - ./oscript
```
+
+
+# Ручная локальная сборка
+
+## Подготовка
+
+Ниже приведены ссылки на дистрибутивы, однако, учтите, что ссылки могут меняться со временем и их актуальность не гарантируется. Нужен dotnet SDK и компилятор C++, скачать можно из любого места, которое нагуглится.
+
+* Установить [MS BuildTools](https://visualstudio.microsoft.com/ru/thank-you-downloading-visual-studio/?sku=buildtools&rel=16), при установке включить таргетинг на .net6, .net4.8, установить компилятор C++.
+
+## Сборка
+
+Запустить Developer Command Prompt (появится в меню Пуск после установки MSBuildTools или Visual Studio). Перейти в каталог репозитория OneScript. Далее приведены команды в консоли Developer Command Prompt
+Сборка выполняется с помощью msbuild. Таргеты:
+
+* CleanAll - очистка результатов предыдущих сборок
+* BuildAll - подготовить файлы для поставки
+* MakeCPP;MakeFDD;MakeSCD;BuildDebugger - отдельные таргеты сборки для подготовки разных типов поставки
+* PrepareDistributionFiles - сборка полных пакетов поставки (включая библиотеки)
+* PackDistributions - подготовка ZIP архивов поставки
+* CreateNuget - создать пакеты для публикации в NuGet
+
+**Параметры сборки**
+
+* VersionPrefix - префикс номера релиза, его основная часть, например, 2.0.0
+* VersionSuffix - суффикс номера, который обычно выступает в качестве произвольного суффикса версионирования по semver, например, beta-786 (необязателен)
+* NoCppCompiler - если True - не установлен компилятор C++, в сборку не будут добавлены компоненты C++ (поддержка NativeApi)
+
+Все поставляемые файлы будут размещены в каталоге `built` в корне репозитория 1Script
+
+### Сборка содержимого дистрибутивов в отдельном каталоге
+
+```bat
+msbuild Build.csproj /t:CleanAll;PrepareDistributionFiles
+```
+
+### Сборка с ручным указанием версии
+
+```bat
+msbuild Build.csproj /t:CleanAll;PrepareDistributionFiles /p:VersionPrefix=2.0.0
+```
+
+### Сборка ZIP-дистрибутивов
+
+```bat
+msbuild Build.csproj /t:CleanAll;PrepareDistributionFiles;PackDistributions /p:VersionPrefix=2.0.0 /p:VersionSuffix=preview223
+```
\ No newline at end of file
diff --git a/install/opm.ospx b/install/opm.ospx
index 661b6ff2b..5fd862e52 100644
Binary files a/install/opm.ospx and b/install/opm.ospx differ
diff --git a/install/package-loader.os b/install/package-loader.os
index ae2b4a3ec..915c41a15 100644
--- a/install/package-loader.os
+++ b/install/package-loader.os
@@ -106,6 +106,9 @@
КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "src", "Модули"));
КаталогиМодулей.Добавить(ОбъединитьПути(Путь, "src", "Modules"));
+ КаталогиВК = Новый Массив;
+ КаталогиВК.Добавить(ОбъединитьПути(Путь, "Components"));
+ КаталогиВК.Добавить(ОбъединитьПути(Путь, "Компоненты"));
Для Каждого мКаталог Из КаталогиКлассов Цикл
@@ -118,6 +121,12 @@
ОбработатьКаталогМодулей(мКаталог, СтандартнаяОбработка, Отказ);
КонецЦикла;
+
+ Для Каждого мКаталог Из КаталогиВК Цикл
+
+ ОбработатьКаталогВК(мКаталог, СтандартнаяОбработка, Отказ);
+
+ КонецЦикла;
КонецПроцедуры
@@ -161,6 +170,75 @@
КонецПроцедуры
+// По соглашению ВК должны лежать в подпапках, названных, как значения перечисления ТипПлатформы.
+// Имя файла, являющегося внешней компонентой должно иметь префикс 1script_
+// Components
+// net4 (фреймворк .net48
+// 1script_barcode.dll
+// dotnet (.net современных версий, он же netcore)
+// 1script_barcode.dll
+// NativeApi
+// Windows_x86
+// 1script_barcode.dll
+// Windows_x86_64
+// 1script_barcode.dll
+// Linux_x86_64
+// 1script_barcode.so
+// остальные не поддерживаются (ЖВПР)
+//
+Процедура ОбработатьКаталогВК(Знач Путь, СтандартнаяОбработка, Отказ)
+
+ СИ = Новый СистемнаяИнформация();
+ МажорнаяВерсия = Лев(СИ.Версия,1);
+
+ Если МажорнаяВерсия = "1" Тогда
+ ОбработатьБиблиотекиCLR(ОбъединитьПути(Путь, "net4"));
+ ИначеЕсли МажорнаяВерсия = "2" Тогда
+ ОбработатьБиблиотекиCLR(ОбъединитьПути(Путь, "dotnet"));
+ Иначе
+ Вывести("Неизвестная мажорная версия системы: " + МажорнаяВерсия);
+ КонецЕсли;
+
+ ОбработатьКомпонентыNativeApi(Путь);
+
+КонецПроцедуры
+
+Процедура ОбработатьБиблиотекиCLR(Путь)
+ КандидатыВКомпоненты = НайтиФайлы(Путь, "1script_*.dll");
+ Для Каждого Кандидат Из КандидатыВКомпоненты Цикл
+ Если Не Кандидат.ЭтоФайл() Тогда
+ Продолжить;
+ КонецЕсли;
+
+ Вывести("Загружаю файл " + Кандидат.Имя);
+ ЗагрузитьБиблиотеку(Кандидат.ПолноеИмя);
+
+ КонецЦикла;
+КонецПроцедуры
+
+Процедура ОбработатьКомпонентыNativeApi(Путь)
+ СИ = Новый СистемнаяИнформация;
+ ИмяПодкаталога = ОбъединитьПути(Путь, Строка(СИ.ТипПлатформы));
+ Вывести("Ищу внешние компоненты в каталоге " + Путь);
+
+ #Если Windows Тогда
+ Расширение = ".dll";
+ #Иначе
+ Расширение = ".so";
+ #КонецЕсли
+
+ КандидатыВКомпоненты = НайтиФайлы(ИмяПодкаталога, "1script_*"+Расширение);
+ Для Каждого Кандидат Из КандидатыВКомпоненты Цикл
+ Если Не Кандидат.ЭтоФайл() Тогда
+ Продолжить;
+ КонецЕсли;
+
+ Вывести("Загружаю файл " + Кандидат.Имя);
+ ПодключитьВнешнююКомпоненту(Кандидат.ПолноеИмя, Кандидат.Имя, ТипВнешнейКомпоненты.Native);
+
+ КонецЦикла;
+КонецПроцедуры
+
Процедура ДобавитьКлассЕслиРанееНеДобавляли(ПутьФайла, ИмяКласса)
Вывести("Добавляю класс, если ранее не добавляли " + ИмяКласса);
Если ВыдаватьОшибкуПриЗагрузкеУжеСуществующихКлассовМодулей Тогда
diff --git a/src/1Script.sln b/src/1Script.sln
index 9da3cfeaf..3f8c681ea 100644
--- a/src/1Script.sln
+++ b/src/1Script.sln
@@ -17,9 +17,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D14BF321-348C-46B8-B96A-43A22BA7AC10}"
ProjectSection(SolutionItems) = preProject
- ..\Build.csproj = ..\Build.csproj
oscommon.targets = oscommon.targets
- ..\Build_Core.csproj = ..\Build_Core.csproj
+ ..\Build.csproj = ..\Build.csproj
..\Jenkinsfile = ..\Jenkinsfile
EndProjectSection
EndProject
diff --git a/src/1Script_Mono.sln b/src/1Script_Mono.sln
deleted file mode 100644
index f138cfbd8..000000000
--- a/src/1Script_Mono.sln
+++ /dev/null
@@ -1,165 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27130.2020
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptEngine", "ScriptEngine\ScriptEngine.csproj", "{F062D1D9-D307-492A-A56B-FF3C55F8F6C0}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ScriptEngine.HostedScript", "ScriptEngine.HostedScript\ScriptEngine.HostedScript.csproj", "{F09A46BD-5737-45E7-BA60-A47C9F7821A9}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "oscript", "oscript\oscript.csproj", "{2590E2BB-CC1F-4775-80ED-451F45C9A4F1}"
- ProjectSection(ProjectDependencies) = postProject
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B} = {795AA2F5-3074-4BC5-A30F-1B6354044D9B}
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StandaloneRunner", "StandaloneRunner\StandaloneRunner.csproj", "{795AA2F5-3074-4BC5-A30F-1B6354044D9B}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D14BF321-348C-46B8-B96A-43A22BA7AC10}"
- ProjectSection(SolutionItems) = preProject
- oscommon.targets = oscommon.targets
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUnitTests", "NUnitTests\NUnitTests.csproj", "{93ACC849-E7E1-4695-B59D-54B3737E48A6}"
- ProjectSection(ProjectDependencies) = postProject
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1} = {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9} = {F09A46BD-5737-45E7-BA60-A47C9F7821A9}
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0} = {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B} = {795AA2F5-3074-4BC5-A30F-1B6354044D9B}
- EndProjectSection
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Component", "Component\Component.csproj", "{B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DebugServer", "DebugServer\DebugServer.csproj", "{C979F151-AA29-47E4-B020-3039BA0986D9}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OneScript.DebugProtocol", "OneScript.DebugProtocol\OneScript.DebugProtocol.csproj", "{727A498F-BF50-42F8-8523-40C0B5B1B233}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "oscriptTests", "oscriptTest\oscriptTests.csproj", "{69A7869C-203C-4F09-AC3F-04E9B52AD7AB}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{91059C5B-526C-4B81-B106-99DEFF542D1F}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HTTPServices", "ASPNETHandler\HTTPServices.csproj", "{B7CD7F52-E387-490E-8F77-E1FB060401B5}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Debug|x86 = Debug|x86
- Release|Any CPU = Release|Any CPU
- Release|x86 = Release|x86
- ReleaseNetStandard|Any CPU = ReleaseNetStandard|Any CPU
- ReleaseNetStandard|x86 = ReleaseNetStandard|x86
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|x86.ActiveCfg = Debug|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|x86.Build.0 = Debug|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|Any CPU.Build.0 = Release|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|x86.ActiveCfg = Release|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|x86.Build.0 = Release|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.ReleaseNetStandard|x86.Build.0 = Release|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|x86.ActiveCfg = Debug|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|x86.Build.0 = Debug|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|Any CPU.Build.0 = Release|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|x86.ActiveCfg = Release|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|x86.Build.0 = Release|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.ReleaseNetStandard|x86.Build.0 = Release|Any CPU
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Debug|Any CPU.ActiveCfg = Debug|x86
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Debug|x86.ActiveCfg = Debug|x86
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Debug|x86.Build.0 = Debug|x86
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Release|Any CPU.ActiveCfg = Release|x86
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Release|x86.ActiveCfg = Release|x86
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Release|x86.Build.0 = Release|x86
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|x86
- {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.ReleaseNetStandard|x86.ActiveCfg = Release|x86
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|x86.ActiveCfg = Debug|x86
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|x86.Build.0 = Debug|x86
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|Any CPU.Build.0 = Release|Any CPU
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|x86.ActiveCfg = Release|x86
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|x86.Build.0 = Release|x86
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.ReleaseNetStandard|x86.ActiveCfg = Release|x86
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|x86.ActiveCfg = Debug|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Any CPU.Build.0 = Release|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|x86.ActiveCfg = Release|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {93ACC849-E7E1-4695-B59D-54B3737E48A6}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|x86.ActiveCfg = Debug|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Any CPU.Build.0 = Release|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|x86.ActiveCfg = Release|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.Debug|x86.ActiveCfg = Debug|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.Release|Any CPU.Build.0 = Release|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.Release|x86.ActiveCfg = Release|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.Release|x86.Build.0 = Release|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {C979F151-AA29-47E4-B020-3039BA0986D9}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Debug|x86.ActiveCfg = Debug|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Debug|x86.Build.0 = Debug|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Release|Any CPU.Build.0 = Release|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Release|x86.ActiveCfg = Release|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.Release|x86.Build.0 = Release|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- {727A498F-BF50-42F8-8523-40C0B5B1B233}.ReleaseNetStandard|x86.Build.0 = Release|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.Debug|x86.ActiveCfg = Debug|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.Release|Any CPU.Build.0 = Release|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.Release|x86.ActiveCfg = Release|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.ReleaseNetStandard|Any CPU.ActiveCfg = ReleaseNetStandard|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.ReleaseNetStandard|Any CPU.Build.0 = ReleaseNetStandard|Any CPU
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Debug|x86.ActiveCfg = Debug|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Debug|x86.Build.0 = Debug|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Release|Any CPU.Build.0 = Release|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Release|x86.ActiveCfg = Release|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.Release|x86.Build.0 = Release|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.ReleaseNetStandard|Any CPU.ActiveCfg = Release|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.ReleaseNetStandard|Any CPU.Build.0 = Release|Any CPU
- {B7CD7F52-E387-490E-8F77-E1FB060401B5}.ReleaseNetStandard|x86.ActiveCfg = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(NestedProjects) = preSolution
- {69A7869C-203C-4F09-AC3F-04E9B52AD7AB} = {91059C5B-526C-4B81-B106-99DEFF542D1F}
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {A4A871EF-C5A7-478F-907E-31C69A869973}
- EndGlobalSection
-EndGlobal
diff --git a/src/OneScript.Core/Commons/Utils.cs b/src/OneScript.Core/Commons/Utils.cs
index b110f0713..1ed8a41bd 100644
--- a/src/OneScript.Core/Commons/Utils.cs
+++ b/src/OneScript.Core/Commons/Utils.cs
@@ -5,7 +5,9 @@ This Source Code Form is subject to the terms of the
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
using System;
+using System.Collections;
using System.Collections.Generic;
+using System.Linq;
namespace OneScript.Commons
{
diff --git a/src/OneScript.Core/Compilation/Binding/SymbolTable.cs b/src/OneScript.Core/Compilation/Binding/SymbolTable.cs
index 7c5ae829c..3a05090cb 100644
--- a/src/OneScript.Core/Compilation/Binding/SymbolTable.cs
+++ b/src/OneScript.Core/Compilation/Binding/SymbolTable.cs
@@ -18,7 +18,7 @@ private struct BindingRecord
public IRuntimeContextInstance target;
}
- private List _bindings = new List();
+ private readonly List _bindings = new List();
public SymbolScope GetScope(int index) => _bindings[index].scope;
diff --git a/src/OneScript.Core/Compilation/CompileTimeSymbolsProvider.cs b/src/OneScript.Core/Compilation/CompileTimeSymbolsProvider.cs
index b7dff4a05..f037926fd 100644
--- a/src/OneScript.Core/Compilation/CompileTimeSymbolsProvider.cs
+++ b/src/OneScript.Core/Compilation/CompileTimeSymbolsProvider.cs
@@ -60,8 +60,8 @@ private static bool IsFiller(MethodInfo methodInfo)
private class SymbolProvider : IModuleSymbolsProvider
{
- private CompileTimeSymbolsProvider _provider;
- private Filler _filler;
+ private readonly CompileTimeSymbolsProvider _provider;
+ private readonly Filler _filler;
public SymbolProvider(CompileTimeSymbolsProvider provider, Filler filler)
{
diff --git a/src/OneScript.Core/Compilation/GlobalPropertiesHolder.cs b/src/OneScript.Core/Compilation/GlobalPropertiesHolder.cs
index 9a830bec7..7f85bf6e9 100644
--- a/src/OneScript.Core/Compilation/GlobalPropertiesHolder.cs
+++ b/src/OneScript.Core/Compilation/GlobalPropertiesHolder.cs
@@ -18,8 +18,8 @@ namespace OneScript.Compilation
{
internal class GlobalPropertiesHolder : IContext
{
- private IndexedNameValueCollection _values= new IndexedNameValueCollection();
- private List _properties = new List();
+ private readonly IndexedNameValueCollection _values= new IndexedNameValueCollection();
+ private readonly List _properties = new List();
public BslPropertyInfo Register(BilingualString names, BslValue value)
{
@@ -90,12 +90,12 @@ public BslValue GetPropValue(BslPropertyInfo property)
public void CallAsProcedure(BslMethodInfo method, IReadOnlyList arguments)
{
- throw new ArgumentException();
+ throw new InvalidOperationException();
}
public BslValue CallAsFunction(BslMethodInfo method, IReadOnlyList arguments)
{
- throw new ArgumentException();
+ throw new InvalidOperationException();
}
#endregion
diff --git a/src/OneScript.Core/Contexts/BslMethodInfo.cs b/src/OneScript.Core/Contexts/BslMethodInfo.cs
index 220f5e896..4d82c6d12 100644
--- a/src/OneScript.Core/Contexts/BslMethodInfo.cs
+++ b/src/OneScript.Core/Contexts/BslMethodInfo.cs
@@ -6,8 +6,10 @@ This Source Code Form is subject to the terms of the
----------------------------------------------------------*/
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using OneScript.Localization;
namespace OneScript.Contexts
{
@@ -20,7 +22,7 @@ public abstract class BslMethodInfo : MethodInfo, INameAndAliasProvider
public abstract string Alias { get; }
- private AnnotationHolder Annotations
+ protected AnnotationHolder Annotations
{
get
{
diff --git a/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs b/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs
index 0dd00e1e4..89ede2c03 100644
--- a/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs
+++ b/src/OneScript.Core/Contexts/BslScriptMethodInfo.cs
@@ -11,6 +11,7 @@ This Source Code Form is subject to the terms of the
using System.Linq;
using System.Reflection;
using OneScript.Contexts.Internal;
+using OneScript.Localization;
namespace OneScript.Contexts
{
@@ -117,5 +118,12 @@ public override MethodInfo GetBaseDefinition()
}
public override ICustomAttributeProvider ReturnTypeCustomAttributes => throw new NotImplementedException();
+
+ public bool HasBslAnnotation(BilingualString name)
+ {
+ return Annotations.GetCustomAttributes(typeof(BslAnnotationAttribute), false)
+ .Cast()
+ .Any(anno => name.HasName(anno.Name));
+ }
}
}
\ No newline at end of file
diff --git a/src/OneScript.Core/Contexts/IPredefinedInterfaceChecker.cs b/src/OneScript.Core/Contexts/IPredefinedInterfaceChecker.cs
new file mode 100644
index 000000000..7491fc76a
--- /dev/null
+++ b/src/OneScript.Core/Contexts/IPredefinedInterfaceChecker.cs
@@ -0,0 +1,23 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System.Collections.Generic;
+using OneScript.Execution;
+
+namespace OneScript.Contexts
+{
+ ///
+ /// Постобработчик построения модуля, регистрирующий специальные аннотации, позволяющий во время компиляции проверить
+ /// что модуль соответствует тому или иному интерфейсу, содержит корректные методы и пр.
+ ///
+ public interface IPredefinedInterfaceChecker
+ {
+ IEnumerable GetRegistrations();
+
+ public void Validate(IExecutableModule module);
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Core/Contexts/PredefinedInterfaceRegistration.cs b/src/OneScript.Core/Contexts/PredefinedInterfaceRegistration.cs
new file mode 100644
index 000000000..661c4ebbf
--- /dev/null
+++ b/src/OneScript.Core/Contexts/PredefinedInterfaceRegistration.cs
@@ -0,0 +1,81 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using OneScript.Localization;
+
+namespace OneScript.Contexts
+{
+ ///
+ /// Опции регистрации предопределенных аннотаций
+ ///
+ public class PredefinedInterfaceRegistration : IEquatable
+ {
+ public PredefinedInterfaceRegistration(
+ MarkerLocation location,
+ BilingualString annotation,
+ BilingualString methodName)
+ {
+ Location = location;
+ Annotation = annotation;
+ MethodName = methodName;
+ }
+
+ public MarkerLocation Location { get; }
+ public BilingualString Annotation { get; }
+ public BilingualString MethodName { get; }
+
+ public PredefinedInterfaceRegistration(MarkerLocation location, BilingualString annotation) : this(location, annotation, null)
+ {
+ }
+
+ ///
+ /// Хелпер для регистрации аннотаций модуля
+ ///
+ /// Регистрируемая аннотация
+ public static PredefinedInterfaceRegistration OnModule(BilingualString annotation)
+ {
+ return new PredefinedInterfaceRegistration(MarkerLocation.ModuleAnnotation, annotation);
+ }
+
+ ///
+ /// Хелпер для регистрации аннотаций на методах
+ ///
+ /// Регистрируемая аннотация
+ /// Метод на котором должна быть расположена аннотация
+ public static PredefinedInterfaceRegistration OnMethod(BilingualString annotation, BilingualString methodName)
+ {
+ return new PredefinedInterfaceRegistration(MarkerLocation.SpecificMethodAnnotation, annotation, methodName);
+ }
+
+ public bool Equals(PredefinedInterfaceRegistration other)
+ {
+ if (ReferenceEquals(null, other)) return false;
+ if (ReferenceEquals(this, other)) return true;
+ return Location == other.Location && Equals(Annotation, other.Annotation) && Equals(MethodName, other.MethodName);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (ReferenceEquals(null, obj)) return false;
+ if (ReferenceEquals(this, obj)) return true;
+ if (obj.GetType() != this.GetType()) return false;
+ return Equals((PredefinedInterfaceRegistration)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode.Combine((int)Location, Annotation, MethodName);
+ }
+ }
+
+ public enum MarkerLocation
+ {
+ ModuleAnnotation,
+ SpecificMethodAnnotation
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Core/Contexts/PredefinedInterfaceResolver.cs b/src/OneScript.Core/Contexts/PredefinedInterfaceResolver.cs
new file mode 100644
index 000000000..ce72f8db6
--- /dev/null
+++ b/src/OneScript.Core/Contexts/PredefinedInterfaceResolver.cs
@@ -0,0 +1,83 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using OneScript.Commons;
+using OneScript.Execution;
+
+namespace OneScript.Contexts
+{
+ // ReSharper disable once ClassNeverInstantiated.Global
+ public class PredefinedInterfaceResolver
+ {
+ private readonly ISet _checkers;
+
+ private class CheckerData : PredefinedInterfaceRegistration
+ {
+ public IPredefinedInterfaceChecker Checker { get; }
+
+ public CheckerData(
+ IPredefinedInterfaceChecker checker,
+ PredefinedInterfaceRegistration source)
+ : base(source.Location, source.Annotation, source.MethodName)
+ {
+ Checker = checker;
+ }
+ }
+
+ public PredefinedInterfaceResolver(IEnumerable checkers)
+ {
+ _checkers = MapCheckers(checkers);
+ }
+
+ public void Resolve(IExecutableModule module)
+ {
+ var triggeredCheckers = new HashSet();
+
+ _checkers
+ .Where(check => !triggeredCheckers.Contains(check.Checker))
+ .Where(check =>
+ check.Location == MarkerLocation.ModuleAnnotation
+ && module.ModuleAttributes.Any(attr => check.Annotation.HasName(attr.Name)))
+ .ForEach(check =>
+ {
+ triggeredCheckers.Add(check.Checker);
+ check.Checker.Validate(module);
+ });
+
+ foreach (var methodInfo in module.Methods.Where(m => m is BslScriptMethodInfo).Cast())
+ {
+ _checkers
+ .Where(check => !triggeredCheckers.Contains(check.Checker))
+ .Where(check =>
+ check.Location == MarkerLocation.SpecificMethodAnnotation &&
+ check.MethodName.HasName(methodInfo.Name) &&
+ methodInfo.HasBslAnnotation(check.Annotation))
+ .ForEach(check =>
+ {
+ triggeredCheckers.Add(check.Checker);
+ check.Checker.Validate(module);
+ });
+ }
+ }
+
+ private ISet MapCheckers(IEnumerable checkers)
+ {
+ var result = new HashSet();
+
+ foreach (var sourceCheck in checkers)
+ {
+ sourceCheck.GetRegistrations().ForEach(x => result.Add(new CheckerData(sourceCheck, x)));
+ }
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Core/Exceptions/InterfaceCheckException.cs b/src/OneScript.Core/Exceptions/InterfaceCheckException.cs
new file mode 100644
index 000000000..d591996b4
--- /dev/null
+++ b/src/OneScript.Core/Exceptions/InterfaceCheckException.cs
@@ -0,0 +1,23 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using OneScript.Localization;
+
+namespace OneScript.Exceptions
+{
+ public class InterfaceCheckException : RuntimeException
+ {
+ public InterfaceCheckException(BilingualString message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ public InterfaceCheckException(BilingualString message) : base(message)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Core/Execution/IExecutableModule.cs b/src/OneScript.Core/Execution/IExecutableModule.cs
index fcd3da430..09fd80b69 100644
--- a/src/OneScript.Core/Execution/IExecutableModule.cs
+++ b/src/OneScript.Core/Execution/IExecutableModule.cs
@@ -5,6 +5,7 @@ This Source Code Form is subject to the terms of the
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
+using System;
using System.Collections.Generic;
using OneScript.Contexts;
using OneScript.Sources;
@@ -25,6 +26,8 @@ public interface IExecutableModule
SourceCode Source { get; }
+ IDictionary Interfaces { get; }
+
const string BODY_METHOD_NAME = "$entry";
}
}
\ No newline at end of file
diff --git a/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs b/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs
index 826162b36..80386d5c5 100644
--- a/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs
+++ b/src/OneScript.Core/Rcw/RcwMembersMetadataCollection.cs
@@ -14,12 +14,12 @@ namespace OneScript.Rcw
public class RcwMembersMetadataCollection where T : RcwMemberMetadata
{
private readonly List _collection = new List();
- private readonly Dictionary _dispIds = new Dictionary();
- private readonly Dictionary _names = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
+ private readonly Dictionary _indexByDispId = new Dictionary();
+ private readonly Dictionary _indexByName = new Dictionary(StringComparer.InvariantCultureIgnoreCase);
- public IReadOnlyDictionary DispatchIds => new ReadOnlyDictionary(_dispIds);
+ public IReadOnlyDictionary ByDispatchId => _indexByDispId;
- public IReadOnlyDictionary Names => new ReadOnlyDictionary(_names);
+ public IReadOnlyDictionary ByName => _indexByName;
public T this[int index] => _collection[index];
@@ -27,15 +27,28 @@ public class RcwMembersMetadataCollection where T : RcwMemberMetadata
public void Add(T item)
{
- if (_dispIds.ContainsKey(item.DispatchId))
+ if (_indexByDispId.TryGetValue(item.DispatchId, out var method))
{
- _names.Add(item.Name, _dispIds[item.DispatchId]);
+ if (method.Name != item.Name)
+ {
+ // добавляют метод, который известен нам, с тем же dispId, но который имеет другое имя
+ _indexByName.Remove(method.Name); // известное нам старое имя этого dispId - инвалидируем
+
+ // добавляемый метод поместим в индекс диспатчей и имен
+ _indexByDispId[item.DispatchId] = item;
+ _indexByName[item.Name] = item;
+ }
+ else
+ {
+ _indexByName[item.Name] = item;
+ }
+
return;
}
_collection.Add(item);
- _dispIds.Add(item.DispatchId, item);
- _names.Add(item.Name, item);
+ _indexByDispId.Add(item.DispatchId, item);
+ _indexByName.Add(item.Name, item);
}
public bool Contains(T item) => _collection.Contains(item);
diff --git a/src/OneScript.Core/Rcw/RcwMetadata.cs b/src/OneScript.Core/Rcw/RcwMetadata.cs
index e4281775d..be04a8e5b 100644
--- a/src/OneScript.Core/Rcw/RcwMetadata.cs
+++ b/src/OneScript.Core/Rcw/RcwMetadata.cs
@@ -128,7 +128,7 @@ private void LoadFuncs(ITypeInfo typeInfo, TYPEATTR typeAttr)
private RcwPropertyMetadata GetOrAddProperty(string propName, int dispId)
{
- if (Properties.Names.TryGetValue(propName, out var md)) return md;
+ if (Properties.ByName.TryGetValue(propName, out var md)) return md;
md = new RcwPropertyMetadata(propName, dispId);
Properties.Add(md);
diff --git a/src/OneScript.Core/Sources/EmptyModule.cs b/src/OneScript.Core/Sources/EmptyModule.cs
index 66226a123..a4d23be98 100644
--- a/src/OneScript.Core/Sources/EmptyModule.cs
+++ b/src/OneScript.Core/Sources/EmptyModule.cs
@@ -7,6 +7,7 @@ This Source Code Form is subject to the terms of the
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using OneScript.Contexts;
using OneScript.Execution;
@@ -14,7 +15,7 @@ namespace OneScript.Sources
{
public sealed class EmptyModule : IExecutableModule
{
- public static IExecutableModule Instance = new EmptyModule();
+ public static readonly IExecutableModule Instance = new EmptyModule();
private EmptyModule()
{
@@ -29,5 +30,7 @@ private EmptyModule()
public IList Methods => Array.Empty();
public BslMethodInfo ModuleBody { get; }
public SourceCode Source { get; }
+
+ public IDictionary Interfaces => new ReadOnlyDictionary(new Dictionary());
}
}
\ No newline at end of file
diff --git a/src/OneScript.Core/Types/ITypeManager.cs b/src/OneScript.Core/Types/ITypeManager.cs
index 01f69ab34..79b21490a 100644
--- a/src/OneScript.Core/Types/ITypeManager.cs
+++ b/src/OneScript.Core/Types/ITypeManager.cs
@@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the
----------------------------------------------------------*/
using System;
+using System.Collections.Generic;
namespace OneScript.Types
{
@@ -25,5 +26,8 @@ public interface ITypeManager
bool IsKnownType(Type type);
bool IsKnownType(string typeName);
+
+ IReadOnlyList RegisteredTypes();
+
}
}
\ No newline at end of file
diff --git a/src/OneScript.Language/LanguageDef.cs b/src/OneScript.Language/LanguageDef.cs
index fadd827f3..ecbbb9c76 100644
--- a/src/OneScript.Language/LanguageDef.cs
+++ b/src/OneScript.Language/LanguageDef.cs
@@ -17,16 +17,13 @@ public static class LanguageDef
static readonly Dictionary _priority = new Dictionary();
public const int MAX_OPERATION_PRIORITY = 8;
- private static readonly LexemTrie _stringToToken = new LexemTrie();
+ private static readonly IdentifiersTrie _stringToToken = new IdentifiersTrie();
- private static readonly LexemTrie _undefined = new LexemTrie();
- private static readonly LexemTrie _booleans = new LexemTrie();
- private static readonly LexemTrie _logicalOp = new LexemTrie();
+ private static readonly IdentifiersTrie _undefined = new IdentifiersTrie();
+ private static readonly IdentifiersTrie _booleans = new IdentifiersTrie();
+ private static readonly IdentifiersTrie _logicalOp = new IdentifiersTrie();
- private static readonly LexemTrie _preprocRegion = new LexemTrie();
- private static readonly LexemTrie _preprocEndRegion = new LexemTrie();
-
- private static readonly LexemTrie _preprocImport = new LexemTrie();
+ private static readonly IdentifiersTrie _preprocImport = new IdentifiersTrie();
const int BUILTINS_INDEX = (int)Token.ByValParam;
@@ -110,6 +107,7 @@ static LanguageDef()
AddToken(Token.RemoveHandler, "УдалитьОбработчик", "RemoveHandler");
AddToken(Token.Async, "Асинх", "Async");
AddToken(Token.Await, "Ждать", "Await");
+ AddToken(Token.Goto, "Перейти", "Goto");
#endregion
@@ -216,11 +214,6 @@ static LanguageDef()
#endregion
- _preprocRegion.Add("Область",true);
- _preprocRegion.Add("Region", true);
- _preprocEndRegion.Add("КонецОбласти", true);
- _preprocEndRegion.Add("EndRegion", true);
-
_preprocImport.Add("Использовать", true);
_preprocImport.Add("Use", true);
}
@@ -292,7 +285,7 @@ public static bool IsUnaryOperator(Token token)
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool IsLiteral(ref Lexem lex)
+ public static bool IsLiteral(in Lexem lex)
{
return lex.Type == LexemType.StringLiteral
|| lex.Type == LexemType.NumberLiteral
@@ -410,18 +403,6 @@ public static bool IsLogicalOperatorString(string content)
return _logicalOp.TryGetValue(content, out var nodeIsFilled) && nodeIsFilled;
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool IsPreprocRegion(string value)
- {
- return _preprocRegion.TryGetValue(value, out var nodeIsFilled) && nodeIsFilled;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static bool IsPreprocEndRegion(string value)
- {
- return _preprocEndRegion.TryGetValue(value, out var nodeIsFilled) && nodeIsFilled;
- }
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsImportDirective(string value)
{
diff --git a/src/OneScript.Language/LexemTrie.cs b/src/OneScript.Language/LexemTrie.cs
deleted file mode 100644
index 5263b4e15..000000000
--- a/src/OneScript.Language/LexemTrie.cs
+++ /dev/null
@@ -1,213 +0,0 @@
-/*----------------------------------------------------------
-This Source Code Form is subject to the terms of the
-Mozilla Public License, v.2.0. If a copy of the MPL
-was not distributed with this file, You can obtain one
-at http://mozilla.org/MPL/2.0/.
-----------------------------------------------------------*/
-
-using System.Collections.Generic;
-using System.Diagnostics;
-
-namespace OneScript.Language
-{
- public class LexemTrie
- {
- private class TrieNode
- {
- public char UCase;
- public char LCase;
-
- public TrieNode next;
- public TrieNode sibling;
- public T value;
- }
-
- private static int _alphabetLength;
- private TrieNode[] _alphabet;
- private int _count;
-
- static LexemTrie()
- {
- var ru = "абвгдеёжзийклмнопрстуфхцчшщьыъэюя";
- var en = "abcdefghijklmnopqrstuvwxyz";
- var symbols = @"+-*/\()[].,<>=;?%0123456789";
-
- var all = symbols +
- ru +
- ru.ToUpper() +
- en +
- en.ToUpper();
-
- _alphabetLength = all.Length;
- }
-
- public LexemTrie()
- {
- _alphabet = new TrieNode[_alphabetLength];
- }
-
- public int Count => _count;
-
- private static int GetIndex(char c)
- {
- var code = (int) c;
-
- if (code >= 1040 && code <= 1103)
- {
- return code - 960;
- }
-
- if (code >= 40 && code <= 57)
- {
- return code - 39;
- }
-
- if (code >= 59 && code <= 63)
- {
- return code - 40;
- }
-
- if (code >= 65 && code <= 93)
- {
- return code - 41;
- }
-
- if (code >= 97 && code <= 122)
- {
- return code - 44;
- }
-
- switch (c)
- {
- case '%':
- return 0;
- case 'Ё':
- return 79;
- case 'ё':
- return 144;
- }
-
- return -1;
- }
-
- private TrieNode GetValueNode(string key)
- {
- var index = GetIndex(key[0]);
- if (index == -1)
- return null;
-
- var node = _alphabet[index];
- if (node == null)
- {
- node = new TrieNode();
- node.LCase = char.ToLower(key[0]);
- node.UCase = char.ToUpper(key[0]);
- _alphabet[GetIndex(node.LCase)] = node;
- _alphabet[GetIndex(node.UCase)] = node;
- }
-
- for (int i = 1; i < key.Length; i++)
- {
- var current = node;
- node = node.next;
- if (node == null)
- {
- var newNode = new TrieNode();
- newNode.LCase = char.ToLower(key[i]);
- newNode.UCase = char.ToUpper(key[i]);
- current.next = newNode;
- node = newNode;
- }
- else if (node.LCase != key[i] && node.UCase != key[i])
- {
- var insert = node.sibling;
- while (insert != null)
- {
- if (insert.LCase == key[i] || insert.UCase == key[i])
- {
- node = insert;
- break;
- }
-
- node = insert;
- insert = insert.sibling;
- }
-
- if (insert == null)
- {
- var newNode = new TrieNode();
- newNode.LCase = char.ToLower(key[i]);
- newNode.UCase = char.ToUpper(key[i]);
- node.sibling = newNode;
- node = newNode;
- }
- }
- }
-
- return node;
- }
-
- public void Add(string key, T value)
- {
- var node = GetValueNode(key);
- Debug.Assert(node != null);
-
- node.value = value;
- ++_count;
- }
-
- public T Get(string key)
- {
- var node = FindNode(key);
- if (node == null)
- {
- throw new KeyNotFoundException();
- }
-
- return node.value;
- }
-
- private TrieNode FindNode(string key)
- {
- var index = GetIndex(key[0]);
- if (index == -1 || _alphabet[index] == null)
- return null;
-
- var node = _alphabet[index];
- for (int i = 1; i < key.Length; i++)
- {
- node = node.next;
- if (node == null)
- return null;
-
- while(node.LCase != key[i] && node.UCase != key[i])
- {
- node = node.sibling;
- if(node == null)
- return null;
- }
- }
-
- return node;
- }
-
- public bool TryGetValue(string key, out T value)
- {
- var node = FindNode(key);
- if (node == null)
- {
- value = default(T);
- return false;
- }
-
- value = node.value;
- return true;
- }
-
- public T this[string key]
- {
- get => Get(key);
- set => Add(key, value);
- }
- }
-}
diff --git a/src/OneScript.Language/LexicalAnalysis/AnnotationLexerState.cs b/src/OneScript.Language/LexicalAnalysis/AnnotationLexerState.cs
index fb6efd65d..8bd933bc3 100644
--- a/src/OneScript.Language/LexicalAnalysis/AnnotationLexerState.cs
+++ b/src/OneScript.Language/LexicalAnalysis/AnnotationLexerState.cs
@@ -9,8 +9,8 @@ namespace OneScript.Language.LexicalAnalysis
{
public class AnnotationLexerState : LexerState
{
- WordLexerState _wordExtractor = new WordLexerState();
const string MESSAGE_ANNOTATION_EXPECTED = "Ожидается имя аннотации";
+ private readonly WordLexerState _wordExtractor = new WordLexerState();
public override Lexem ReadNextLexem(SourceCodeIterator iterator)
{
diff --git a/src/OneScript.Language/LexicalAnalysis/FullSourceLexer.cs b/src/OneScript.Language/LexicalAnalysis/FullSourceLexer.cs
index 72aed2aac..0fc6c88c2 100644
--- a/src/OneScript.Language/LexicalAnalysis/FullSourceLexer.cs
+++ b/src/OneScript.Language/LexicalAnalysis/FullSourceLexer.cs
@@ -23,6 +23,7 @@ public class FullSourceLexer : ILexer
private readonly LexerState _commentState = new CommentLexerState();
private readonly LexerState _annotationState = new AnnotationLexerState();
private readonly LexerState _directiveState = new PreprocessorDirectiveLexerState();
+ private readonly LexerState _labelState = new LabelLexerState();
private readonly FixedLexerState _fixedState = new FixedLexerState();
@@ -119,6 +120,10 @@ private void SelectState()
{
_state = _annotationState;
}
+ else if (cs == SpecialChars.Tilde)
+ {
+ _state = _labelState;
+ }
else
{
var cp = _iterator.GetErrorPosition();
diff --git a/src/OneScript.Language/LexicalAnalysis/ISourceCodeIndexer.cs b/src/OneScript.Language/LexicalAnalysis/ISourceCodeIndexer.cs
index b6e5b406c..84f9521c1 100644
--- a/src/OneScript.Language/LexicalAnalysis/ISourceCodeIndexer.cs
+++ b/src/OneScript.Language/LexicalAnalysis/ISourceCodeIndexer.cs
@@ -9,6 +9,6 @@ namespace OneScript.Language.LexicalAnalysis
{
public interface ISourceCodeIndexer
{
- string GetCodeLine(int index);
+ string GetCodeLine(int lineNumber);
}
}
diff --git a/src/OneScript.Language/LexicalAnalysis/LabelLexerState.cs b/src/OneScript.Language/LexicalAnalysis/LabelLexerState.cs
new file mode 100644
index 000000000..607b53946
--- /dev/null
+++ b/src/OneScript.Language/LexicalAnalysis/LabelLexerState.cs
@@ -0,0 +1,60 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System.Diagnostics;
+using OneScript.Localization;
+
+namespace OneScript.Language.LexicalAnalysis
+{
+ public class LabelLexerState : LexerState
+ {
+ private static BilingualString MESSAGE_NAME_EXPECTED = new BilingualString(
+ "Ожидается имя метки",
+ "Label name expected"
+ );
+
+ private static BilingualString INVALID_LABEL = new BilingualString(
+ "Неверно задана метка",
+ "Invalid label definition"
+ );
+
+ private readonly WordLexerState _wordExtractor = new WordLexerState();
+
+ public override Lexem ReadNextLexem(SourceCodeIterator iterator)
+ {
+ Debug.Assert(iterator.CurrentSymbol == SpecialChars.Tilde);
+
+ var start = new CodeRange(iterator.CurrentLine, iterator.CurrentColumn);
+ iterator.MoveNext();
+ if (!iterator.MoveToContent())
+ throw CreateExceptionOnCurrentLine(MESSAGE_NAME_EXPECTED.ToString(), iterator);
+
+ if (!char.IsLetter(iterator.CurrentSymbol))
+ throw CreateExceptionOnCurrentLine(MESSAGE_NAME_EXPECTED.ToString(), iterator);
+
+ var result = _wordExtractor.ReadNextLexem(iterator);
+ if (!LanguageDef.IsUserSymbol(result))
+ {
+ throw CreateExceptionOnCurrentLine(INVALID_LABEL.ToString(), iterator);
+ }
+
+ result.Type = LexemType.LabelRef;
+ if (iterator.CurrentSymbol == SpecialChars.Colon)
+ {
+ result.Type = LexemType.Label;
+ var tail = iterator.ReadToLineEnd();
+ if (tail.Trim().Length != 0)
+ {
+ throw CreateExceptionOnCurrentLine(INVALID_LABEL.ToString(), iterator);
+ }
+ }
+
+ result.Location = start;
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Language/LexicalAnalysis/LexemType.cs b/src/OneScript.Language/LexicalAnalysis/LexemType.cs
index 48f8c5fc6..86723c470 100644
--- a/src/OneScript.Language/LexicalAnalysis/LexemType.cs
+++ b/src/OneScript.Language/LexicalAnalysis/LexemType.cs
@@ -22,6 +22,8 @@ public enum LexemType
PreprocessorDirective,
Annotation,
Comment,
+ Label,
+ LabelRef,
EndOfText
}
}
diff --git a/src/OneScript.Language/LexicalAnalysis/PreprocessorDirectiveLexerState.cs b/src/OneScript.Language/LexicalAnalysis/PreprocessorDirectiveLexerState.cs
index 01070638e..95a676ffb 100644
--- a/src/OneScript.Language/LexicalAnalysis/PreprocessorDirectiveLexerState.cs
+++ b/src/OneScript.Language/LexicalAnalysis/PreprocessorDirectiveLexerState.cs
@@ -11,7 +11,7 @@ namespace OneScript.Language.LexicalAnalysis
{
public class PreprocessorDirectiveLexerState : LexerState
{
- WordLexerState _wordExtractor = new WordLexerState();
+ private readonly WordLexerState _wordExtractor = new WordLexerState();
const string MESSAGE_DIRECTIVE_EXPECTED = "Ожидается директива препроцессора";
public override Lexem ReadNextLexem(SourceCodeIterator iterator)
diff --git a/src/OneScript.Language/LexicalAnalysis/Token.cs b/src/OneScript.Language/LexicalAnalysis/Token.cs
index fc3fd7824..aca7738f1 100644
--- a/src/OneScript.Language/LexicalAnalysis/Token.cs
+++ b/src/OneScript.Language/LexicalAnalysis/Token.cs
@@ -43,7 +43,8 @@ public enum Token
RemoveHandler,
Async,
Await,
-
+ Goto,
+
// operators
Plus,
Minus,
diff --git a/src/OneScript.Language/Localization/BilingualString.cs b/src/OneScript.Language/Localization/BilingualString.cs
index a4aaf9f01..baed18d03 100644
--- a/src/OneScript.Language/Localization/BilingualString.cs
+++ b/src/OneScript.Language/Localization/BilingualString.cs
@@ -5,6 +5,7 @@ This Source Code Form is subject to the terms of the
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
+using System;
using System.Globalization;
namespace OneScript.Localization
@@ -55,6 +56,11 @@ public override string ToString()
return Localize(Russian, English);
}
+ public bool HasName(string name, StringComparison comparison = StringComparison.CurrentCultureIgnoreCase)
+ {
+ return string.Equals(Russian, name, comparison) || string.Equals(English, name, comparison);
+ }
+
public static bool UseRussianLocale => CultureInfo.CurrentCulture.Parent.Equals(RussianCulture);
public static string Localize(string russian, string english)
diff --git a/src/OneScript.Language/OneScript.Language.csproj b/src/OneScript.Language/OneScript.Language.csproj
index b4a2f7bda..404476e0e 100644
--- a/src/OneScript.Language/OneScript.Language.csproj
+++ b/src/OneScript.Language/OneScript.Language.csproj
@@ -22,6 +22,7 @@
true
false
+ DEBUG;TRACE
diff --git a/src/OneScript.Language/Sources/SourceCode.cs b/src/OneScript.Language/Sources/SourceCode.cs
index 8d2be16a1..a31e60652 100644
--- a/src/OneScript.Language/Sources/SourceCode.cs
+++ b/src/OneScript.Language/Sources/SourceCode.cs
@@ -35,9 +35,9 @@ public SourceCodeIterator CreateIterator()
public string GetSourceCode() => _source.GetSourceCode();
- public string GetCodeLine(int index)
+ public string GetCodeLine(int lineNumber)
{
- return _indexer?.GetCodeLine(index);
+ return _indexer?.GetCodeLine(lineNumber);
}
public override string ToString() => Name ?? Location;
diff --git a/src/OneScript.Language/SpecialChars.cs b/src/OneScript.Language/SpecialChars.cs
index fb46c4f42..cfc96e761 100644
--- a/src/OneScript.Language/SpecialChars.cs
+++ b/src/OneScript.Language/SpecialChars.cs
@@ -18,6 +18,8 @@ public static class SpecialChars
public const char QuestionMark = '?';
public const char Preprocessor = '#';
public const char Annotation = '&';
+ public const char Tilde = '~';
+ public const char Colon = ':';
public static bool IsOperatorChar(char symbol)
{
diff --git a/src/OneScript.Language/SyntaxAnalysis/AstNodes/ErrorTerminalNode.cs b/src/OneScript.Language/SyntaxAnalysis/AstNodes/ErrorTerminalNode.cs
new file mode 100644
index 000000000..a4a3c76f9
--- /dev/null
+++ b/src/OneScript.Language/SyntaxAnalysis/AstNodes/ErrorTerminalNode.cs
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using OneScript.Language.LexicalAnalysis;
+
+namespace OneScript.Language.SyntaxAnalysis.AstNodes
+{
+ ///
+ /// Нода ошибочного синтаксиса
+ ///
+ public class ErrorTerminalNode : TerminalNode
+ {
+ public ErrorTerminalNode() : base(NodeKind.Unknown)
+ {
+ }
+
+ public ErrorTerminalNode(Lexem lexem) : base(NodeKind.Unknown, lexem)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Language/SyntaxAnalysis/AstNodes/LabelNode.cs b/src/OneScript.Language/SyntaxAnalysis/AstNodes/LabelNode.cs
new file mode 100644
index 000000000..9721e90ce
--- /dev/null
+++ b/src/OneScript.Language/SyntaxAnalysis/AstNodes/LabelNode.cs
@@ -0,0 +1,21 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using OneScript.Language.LexicalAnalysis;
+
+namespace OneScript.Language.SyntaxAnalysis.AstNodes
+{
+ public class LabelNode : LineMarkerNode
+ {
+ public LabelNode(Lexem labelLexem) : base(labelLexem.Location, NodeKind.Label)
+ {
+ LabelName = labelLexem.Content;
+ }
+
+ public string LabelName { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Language/SyntaxAnalysis/AstNodes/MethodNode.cs b/src/OneScript.Language/SyntaxAnalysis/AstNodes/MethodNode.cs
index d7de41a27..07aa269a3 100644
--- a/src/OneScript.Language/SyntaxAnalysis/AstNodes/MethodNode.cs
+++ b/src/OneScript.Language/SyntaxAnalysis/AstNodes/MethodNode.cs
@@ -17,6 +17,8 @@ public MethodNode() : base(NodeKind.Method)
{
}
+ public bool IsAsync { get; set; }
+
public MethodSignatureNode Signature { get; private set; }
public BslSyntaxNode MethodBody { get; private set; }
diff --git a/src/OneScript.Language/SyntaxAnalysis/AstNodes/UnaryOperationNode.cs b/src/OneScript.Language/SyntaxAnalysis/AstNodes/UnaryOperationNode.cs
index dddcaf793..05e9b80cd 100644
--- a/src/OneScript.Language/SyntaxAnalysis/AstNodes/UnaryOperationNode.cs
+++ b/src/OneScript.Language/SyntaxAnalysis/AstNodes/UnaryOperationNode.cs
@@ -13,7 +13,7 @@ public class UnaryOperationNode : NonTerminalNode
{
public Token Operation { get; }
- public UnaryOperationNode(Lexem operation) : base(NodeKind.UnaryOperation)
+ public UnaryOperationNode(Lexem operation) : base(NodeKind.UnaryOperation, operation)
{
Operation = operation.Token;
}
diff --git a/src/OneScript.Language/SyntaxAnalysis/BslSyntaxWalker.cs b/src/OneScript.Language/SyntaxAnalysis/BslSyntaxWalker.cs
index fbeae0c73..7c2b352da 100644
--- a/src/OneScript.Language/SyntaxAnalysis/BslSyntaxWalker.cs
+++ b/src/OneScript.Language/SyntaxAnalysis/BslSyntaxWalker.cs
@@ -51,9 +51,19 @@ private void CreateVisitors()
_nodeVisitors[(int)NodeKind.RemoveHandler] = VisitHandlerOperation;
_nodeVisitors[(int)NodeKind.NewObject] = (x) => VisitNewObjectCreation((NewObjectNode)x);
_nodeVisitors[(int)NodeKind.Preprocessor] = (x) => VisitPreprocessorDirective((PreprocessorDirectiveNode)x);
+ _nodeVisitors[(int)NodeKind.Goto] = (x) => VisitGotoNode((NonTerminalNode)x);
+ _nodeVisitors[(int)NodeKind.Label] = (x) => VisitLabelNode((LabelNode)x);
}
+ protected virtual void VisitGotoNode(NonTerminalNode node)
+ {
+ }
+
+ protected virtual void VisitLabelNode(LabelNode node)
+ {
+ }
+
protected void SetDefaultVisitorFor(NodeKind kind, Action action)
{
_nodeVisitors[(int)kind] = action;
@@ -158,10 +168,20 @@ protected virtual void VisitStatement(BslSyntaxNode statement)
VisitGlobalProcedureCall(statement as CallNode);
else if (statement.Kind == NodeKind.DereferenceOperation)
VisitProcedureDereference(statement);
+ else if (statement.Kind == NodeKind.UnaryOperation && statement is UnaryOperationNode
+ {
+ Operation: Token.Await
+ } unaryOp)
+ VisitGlobalAwaitCall(unaryOp);
else
DefaultVisit(statement);
}
+ private void VisitGlobalAwaitCall(UnaryOperationNode awaitStatement)
+ {
+ VisitStatement(awaitStatement.Children[0]);
+ }
+
protected virtual void VisitAssignment(BslSyntaxNode assignment)
{
var left = assignment.Children[0];
diff --git a/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs b/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs
index 87e99f83f..9701bb69b 100644
--- a/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs
+++ b/src/OneScript.Language/SyntaxAnalysis/DefaultBslParser.cs
@@ -27,6 +27,7 @@ public class DefaultBslParser
private bool _isMethodsDefined;
private bool _isStatementsDefined;
private bool _isInFunctionScope;
+ private bool _isInAsyncMethod;
private bool _lastDereferenceIsWritable;
private readonly Stack _tokenStack = new Stack();
@@ -286,7 +287,8 @@ private void BuildMethodsSection()
{
if (_lastExtractedLexem.Type != LexemType.Annotation
&& _lastExtractedLexem.Token != Token.Procedure
- && _lastExtractedLexem.Token != Token.Function)
+ && _lastExtractedLexem.Token != Token.Function
+ && _lastExtractedLexem.Token != Token.Async)
{
return;
}
@@ -301,7 +303,7 @@ private void BuildMethodsSection()
while (true)
{
BuildAnnotations();
- if (_lastExtractedLexem.Token == Token.Procedure || _lastExtractedLexem.Token == Token.Function)
+ if (IsStartOfMethod(_lastExtractedLexem))
{
if (!sectionExist)
{
@@ -324,14 +326,26 @@ private void BuildMethodsSection()
}
}
+ private static bool IsStartOfMethod(in Lexem lex)
+ {
+ return lex.Token == Token.Async || lex.Token == Token.Procedure || lex.Token == Token.Function;
+ }
+
private void BuildMethod()
{
- Debug.Assert(_lastExtractedLexem.Token == Token.Procedure || _lastExtractedLexem.Token == Token.Function);
+ Debug.Assert(IsStartOfMethod(_lastExtractedLexem));
var method = _nodeContext.AddChild(new MethodNode());
ApplyAnnotations(method);
PushContext(method);
+ if (_lastExtractedLexem.Token == Token.Async)
+ {
+ method.IsAsync = true;
+ _isInAsyncMethod = true;
+ NextLexem();
+ }
+
try
{
BuildMethodSignature();
@@ -345,6 +359,7 @@ private void BuildMethod()
_isInFunctionScope = false;
_inMethodScope = false;
_isStatementsDefined = false;
+ _isInAsyncMethod = false;
PopContext();
}
}
@@ -382,9 +397,8 @@ private void BuildMethodBody()
private void BuildMethodSignature()
{
- var isFunction = _lastExtractedLexem.Token == Token.Function;
-
var signature = _nodeContext.AddChild(new MethodSignatureNode(_lastExtractedLexem));
+ var isFunction = _lastExtractedLexem.Token == Token.Function;
CreateChild(signature, isFunction? NodeKind.Function : NodeKind.Procedure, _lastExtractedLexem);
_isInFunctionScope = isFunction;
NextLexem();
@@ -471,7 +485,7 @@ private bool BuildDefaultParameterValue(NonTerminalNode param, NodeKind nodeKind
NextLexem();
}
- if (LanguageDef.IsLiteral(ref _lastExtractedLexem))
+ if (LanguageDef.IsLiteral(_lastExtractedLexem))
{
string literalText = _lastExtractedLexem.Content;
if (hasSign)
@@ -607,6 +621,12 @@ private void BuildCodeBatch(params Token[] endTokens)
continue;
}
+ if (_lastExtractedLexem.Type == LexemType.Label)
+ {
+ DefineLabel(_lastExtractedLexem);
+ continue;
+ }
+
if (_lastExtractedLexem.Type != LexemType.Identifier && _lastExtractedLexem.Token != Token.EndOfText)
{
AddError(LocalizedErrors.UnexpectedOperation());
@@ -628,6 +648,13 @@ private void BuildCodeBatch(params Token[] endTokens)
PopStructureToken();
}
+ private void DefineLabel(Lexem label)
+ {
+ var node = new LabelNode(label);
+ _nodeContext.AddChild(node);
+ NextLexem();
+ }
+
#region Statements
private void BuildStatement()
@@ -676,7 +703,13 @@ private void BuildComplexStructureStatement()
case Token.AddHandler:
case Token.RemoveHandler:
BuildEventHandlerOperation(_lastExtractedLexem.Token);
- break;
+ break;
+ case Token.Await:
+ BuildGlobalCallAwaitOperator();
+ break;
+ case Token.Goto:
+ BuildGotoOperator();
+ break;
default:
var expected = _tokenStack.Peek();
AddError(LocalizedErrors.TokenExpected(expected));
@@ -684,6 +717,64 @@ private void BuildComplexStructureStatement()
}
}
+ private void BuildGlobalCallAwaitOperator()
+ {
+ Debug.Assert(_lastExtractedLexem.Token == Token.Await);
+
+ _nodeContext.AddChild(TerminalNode());
+ }
+
+
+ private BslSyntaxNode BuildExpressionAwaitOperator(Lexem lexem)
+ {
+ Debug.Assert(_lastExtractedLexem.Token == Token.Await);
+
+ NextLexem();
+
+ var argument = SelectTerminalNode(_lastExtractedLexem, false);
+ if (argument != default)
+ {
+ CheckAsyncMethod();
+ var awaitOperator = new UnaryOperationNode(lexem);
+ awaitOperator.AddChild(argument);
+ return awaitOperator;
+ }
+ else if (!_isInAsyncMethod)
+ {
+ // это просто переменная Ждать или метод Ждать
+ return CallOrVariable(lexem);
+ }
+ else
+ {
+ AddError(LocalizedErrors.ExpressionSyntax());
+ return new ErrorTerminalNode(_lastExtractedLexem);
+ }
+ }
+
+ private void BuildGotoOperator()
+ {
+ var gotoNode = new NonTerminalNode(NodeKind.Goto, _lastExtractedLexem);
+ NextLexem();
+
+ if (_lastExtractedLexem.Type != LexemType.LabelRef)
+ {
+ AddError(LocalizedErrors.LabelNameExpected());
+ }
+
+ gotoNode.AddChild(new LabelNode(_lastExtractedLexem));
+ NextLexem();
+
+ _nodeContext.AddChild(gotoNode);
+ }
+
+ private void CheckAsyncMethod()
+ {
+ if (!_isInAsyncMethod)
+ {
+ AddError(LocalizedErrors.AwaitMustBeInAsyncMethod(), false);
+ }
+ }
+
private void BuildIfStatement()
{
var condition = _nodeContext.AddChild(new ConditionNode(_lastExtractedLexem));
@@ -1019,10 +1110,15 @@ private void BuildAssignment(NonTerminalNode batch)
private BslSyntaxNode BuildGlobalCall(Lexem identifier)
{
- var target = NodeBuilder.CreateNode(NodeKind.Identifier, identifier);
NextLexem();
- if (_lastExtractedLexem.Token != Token.OpenPar)
+ return CallOrVariable(identifier);
+ }
+
+ private BslSyntaxNode CallOrVariable(Lexem identifier)
+ {
+ var target = NodeBuilder.CreateNode(NodeKind.Identifier, identifier);
+ if (_lastExtractedLexem.Token != Token.OpenPar)
{
_lastDereferenceIsWritable = true; // одиночный идентификатор
}
@@ -1097,7 +1193,6 @@ private void BuildCallArgument(NonTerminalNode argsList)
}
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void BuildLastDefaultArg(NonTerminalNode argsList)
{
NextLexem();
@@ -1253,9 +1348,18 @@ private BslSyntaxNode BuildExpressionUpTo(NonTerminalNode parent, Token stopToke
else
{
if (_lastExtractedLexem.Token == Token.EndOfText)
+ {
AddError(LocalizedErrors.UnexpectedEof());
+ }
else
- AddError(LocalizedErrors.ExpressionSyntax());
+ {
+ SkipToNextStatement(new []{stopToken});
+ AddError(LocalizedErrors.ExpressionSyntax(), false);
+ if (_lastExtractedLexem.Token == stopToken)
+ {
+ NextLexem();
+ }
+ }
node = default;
}
@@ -1276,7 +1380,6 @@ private void BuildOptionalExpression(NonTerminalNode parent, Token stopToken)
#region Operators
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static BslSyntaxNode MakeBinaryOperationNode(BslSyntaxNode firstArg, BslSyntaxNode secondArg, in Lexem lexem)
{
var node = new BinaryOperationNode(lexem);
@@ -1285,7 +1388,6 @@ private static BslSyntaxNode MakeBinaryOperationNode(BslSyntaxNode firstArg, Bsl
return node;
}
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
private BslSyntaxNode BuildParenthesis()
{
if (_lastExtractedLexem.Token == Token.OpenPar)
@@ -1307,34 +1409,45 @@ private BslSyntaxNode BuildParenthesis()
#endregion
private BslSyntaxNode TerminalNode()
+ {
+ BslSyntaxNode node = SelectTerminalNode(_lastExtractedLexem, true);
+ if (node == default)
+ {
+ AddError(LocalizedErrors.ExpressionSyntax());
+ }
+
+ return node;
+ }
+
+ private BslSyntaxNode SelectTerminalNode(in Lexem currentLexem, bool supportAwait)
{
BslSyntaxNode node = default;
- if (LanguageDef.IsLiteral(ref _lastExtractedLexem))
+ if (LanguageDef.IsLiteral(currentLexem))
{
- node = NodeBuilder.CreateNode(NodeKind.Constant, _lastExtractedLexem);
+ node = NodeBuilder.CreateNode(NodeKind.Constant, currentLexem);
NextLexem();
}
- else if (LanguageDef.IsUserSymbol(in _lastExtractedLexem))
+ else if (LanguageDef.IsUserSymbol(currentLexem))
{
- node = BuildGlobalCall(_lastExtractedLexem);
+ node = BuildGlobalCall(currentLexem);
}
- else if(_lastExtractedLexem.Token == Token.NewObject)
+ else if(currentLexem.Token == Token.NewObject)
{
node = BuildNewObjectCreation();
}
- else if (_lastExtractedLexem.Token == Token.Question)
+ else if (currentLexem.Token == Token.Question)
{
node = BuildQuestionOperator();
}
- else if (LanguageDef.IsBuiltInFunction(_lastExtractedLexem.Token))
+ else if (LanguageDef.IsBuiltInFunction(currentLexem.Token))
{
- node = BuildGlobalCall(_lastExtractedLexem);
+ node = BuildGlobalCall(currentLexem);
}
- else
+ else if (supportAwait && currentLexem.Token == Token.Await)
{
- AddError(LocalizedErrors.ExpressionSyntax());
+ node = BuildExpressionAwaitOperator(currentLexem);
}
-
+
return node;
}
@@ -1486,8 +1599,9 @@ private void NewObjectStaticConstructor(NonTerminalNode node)
}
}
- #endregion
-
+ #endregion
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void NextLexem()
{
_lastExtractedLexem = _lexer.NextLexem();
diff --git a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs
index b2f8b73fe..e0b96014f 100644
--- a/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs
+++ b/src/OneScript.Language/SyntaxAnalysis/LocalizedErrors.cs
@@ -43,6 +43,9 @@ private static CodeError Create(string ru, string en, [CallerMemberName] string
public static CodeError IdentifierExpected()
=> Create("Ожидается идентификатор", "Identifier expecting");
+
+ public static CodeError LabelNameExpected()
+ => Create("Ожидается имя метки", "Label name expected");
public static CodeError ExpressionSyntax()
=> Create("Ошибка в выражении", "Expression syntax error");
@@ -60,6 +63,11 @@ public static CodeError ExportedLocalVar(string varName)
$"Local variable can't be exported ({varName})");
}
+ public static CodeError AwaitMustBeInAsyncMethod() => Create(
+ "Оператор Ждать (Await) может употребляться только в асинхронных процедурах или функциях",
+ "Operator Await can be used only in async procedures or functions"
+ );
+
public static CodeError LiteralExpected() => Create("Ожидается константа", "Constant expected");
public static CodeError NumberExpected() => Create("Ожидается числовая константа", "Numeric constant expected");
@@ -134,5 +142,8 @@ public static CodeError DuplicateMethodDefinition(string methodName) =>
public static CodeError SymbolNotFound(string symbol) =>
Create($"Неизвестный символ: {symbol}", $"Symbol not found {symbol}");
+
+ public static CodeError AsyncMethodsNotSupported() =>
+ Create("Асинхронные методы не поддерживаются", "Async methods aren't supported");
}
}
\ No newline at end of file
diff --git a/src/OneScript.Language/SyntaxAnalysis/NodeKind.cs b/src/OneScript.Language/SyntaxAnalysis/NodeKind.cs
index bc76bca70..975941278 100644
--- a/src/OneScript.Language/SyntaxAnalysis/NodeKind.cs
+++ b/src/OneScript.Language/SyntaxAnalysis/NodeKind.cs
@@ -61,6 +61,8 @@ public enum NodeKind
RemoveHandler,
Preprocessor,
Import,
- TopLevelExpression
+ TopLevelExpression,
+ Label,
+ Goto
}
}
\ No newline at end of file
diff --git a/src/OneScript.Language/SyntaxAnalysis/RegionDirectiveHandler.cs b/src/OneScript.Language/SyntaxAnalysis/RegionDirectiveHandler.cs
index 90a05ad03..d659ce4da 100644
--- a/src/OneScript.Language/SyntaxAnalysis/RegionDirectiveHandler.cs
+++ b/src/OneScript.Language/SyntaxAnalysis/RegionDirectiveHandler.cs
@@ -12,8 +12,8 @@ namespace OneScript.Language.SyntaxAnalysis
{
public class RegionDirectiveHandler : DirectiveHandlerBase
{
- private readonly LexemTrie _preprocRegion = new LexemTrie();
- private readonly LexemTrie _preprocEndRegion = new LexemTrie();
+ private readonly IdentifiersTrie _preprocRegion = new IdentifiersTrie();
+ private readonly IdentifiersTrie _preprocEndRegion = new IdentifiersTrie();
private int _regionsNesting = 0;
diff --git a/src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs b/src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs
new file mode 100644
index 000000000..73b949967
--- /dev/null
+++ b/src/OneScript.Language/SyntaxAnalysis/SingleWordModuleAnnotationHandler.cs
@@ -0,0 +1,78 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using OneScript.Language.LexicalAnalysis;
+using OneScript.Language.SyntaxAnalysis.AstNodes;
+using OneScript.Localization;
+
+namespace OneScript.Language.SyntaxAnalysis
+{
+ ///
+ /// Обработчик аннотаций модуля, состоящих из одного слова
+ ///
+ public class SingleWordModuleAnnotationHandler : ModuleAnnotationDirectiveHandler
+ {
+ private readonly ILexer _allLineContentLexer;
+ private readonly ISet _knownNames = new HashSet(StringComparer.CurrentCultureIgnoreCase);
+
+ public SingleWordModuleAnnotationHandler(ISet knownNames, IErrorSink errorSink) : base(errorSink)
+ {
+ var builder = new LexerBuilder();
+ builder.Detect((cs, i) => !char.IsWhiteSpace(cs))
+ .HandleWith(new WordLexerState());
+
+ _allLineContentLexer = builder.Build();
+ _knownNames = knownNames;
+ }
+
+ public SingleWordModuleAnnotationHandler(ISet knownNames, IErrorSink errorSink) : base(errorSink)
+ {
+ var builder = new LexerBuilder();
+ builder.Detect((cs, i) => !char.IsWhiteSpace(cs))
+ .HandleWith(new WordLexerState());
+
+ _allLineContentLexer = builder.Build();
+
+ foreach (var twoNames in knownNames)
+ {
+ _knownNames.Add(twoNames.Russian);
+ _knownNames.Add(twoNames.English);
+ }
+ }
+
+ protected override bool DirectiveSupported(string directive)
+ {
+ return _knownNames.Contains(directive);
+ }
+
+ protected override void ParseAnnotationInternal(ref Lexem lastExtractedLexem, ILexer lexer, ParserContext parserContext)
+ {
+ var node = new AnnotationNode(NodeKind.Annotation, lastExtractedLexem);
+ _allLineContentLexer.Iterator = lexer.Iterator;
+
+ parserContext.AddChild(node);
+
+ // после ничего не должно находиться
+ var nextLexem = _allLineContentLexer.NextLexemOnSameLine();
+ lastExtractedLexem = lexer.NextLexem(); // сдвиг основного лексера
+ if (nextLexem.Type != LexemType.EndOfText)
+ {
+ var err = LocalizedErrors.ExpressionSyntax();
+ err.Position = new ErrorPositionInfo
+ {
+ LineNumber = node.Location.LineNumber,
+ ColumnNumber = node.Location.ColumnNumber,
+ Code = lexer.Iterator.GetCodeLine(node.Location.LineNumber),
+ ModuleName = lexer.Iterator.Source.Name
+ };
+ ErrorSink.AddError(err);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.Native/Compiler/DynamicModule.cs b/src/OneScript.Native/Compiler/DynamicModule.cs
index 3c9dbe796..7d0bfb6e4 100644
--- a/src/OneScript.Native/Compiler/DynamicModule.cs
+++ b/src/OneScript.Native/Compiler/DynamicModule.cs
@@ -5,6 +5,7 @@ This Source Code Form is subject to the terms of the
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
+using System;
using System.Collections.Generic;
using System.Linq;
using OneScript.Contexts;
@@ -26,5 +27,7 @@ public class DynamicModule : IExecutableModule
public BslMethodInfo ModuleBody => Methods.FirstOrDefault(x => x.Name == IExecutableModule.BODY_METHOD_NAME);
public SourceCode Source { get; set; }
+
+ public IDictionary Interfaces { get; } = new Dictionary();
}
}
\ No newline at end of file
diff --git a/src/OneScript.Native/Compiler/ModuleCompiler.cs b/src/OneScript.Native/Compiler/ModuleCompiler.cs
index 07c200a31..61acb2044 100644
--- a/src/OneScript.Native/Compiler/ModuleCompiler.cs
+++ b/src/OneScript.Native/Compiler/ModuleCompiler.cs
@@ -5,6 +5,7 @@ This Source Code Form is subject to the terms of the
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
+using System;
using System.Linq;
using OneScript.Compilation;
using OneScript.Compilation.Binding;
@@ -166,8 +167,22 @@ protected override void VisitModuleVariable(VariableDefinitionNode varNode)
}
}
+ protected override void VisitGotoNode(NonTerminalNode node)
+ {
+ throw new NotSupportedException();
+ }
+
+ protected override void VisitLabelNode(LabelNode node)
+ {
+ throw new NotSupportedException();
+ }
+
protected override void VisitMethod(MethodNode methodNode)
{
+ if (methodNode.IsAsync)
+ {
+ AddError(LocalizedErrors.AsyncMethodsNotSupported(), methodNode.Location);
+ }
var methodSymbol = Symbols.GetScope(Symbols.ScopeCount - 1).Methods[methodNode.Signature.MethodName];
var methodInfo = (BslNativeMethodInfo)methodSymbol.Method;
diff --git a/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs b/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs
index 6ff0b9183..8cdf4ad8c 100644
--- a/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs
+++ b/src/OneScript.Native/Compiler/NativeRuntimeAnnotationHandler.cs
@@ -6,57 +6,28 @@ This Source Code Form is subject to the terms of the
----------------------------------------------------------*/
using System;
+using System.Collections.Generic;
using OneScript.Language;
using OneScript.Language.LexicalAnalysis;
using OneScript.Language.SyntaxAnalysis;
using OneScript.Language.SyntaxAnalysis.AstNodes;
+using OneScript.Localization;
namespace OneScript.Native.Compiler
{
- public class NativeRuntimeAnnotationHandler : ModuleAnnotationDirectiveHandler
+ public class NativeRuntimeAnnotationHandler : SingleWordModuleAnnotationHandler
{
- private readonly ILexer _allLineContentLexer;
-
- public NativeRuntimeAnnotationHandler(IErrorSink errorSink) : base(errorSink)
- {
- var builder = new LexerBuilder();
- builder.Detect((cs, i) => !char.IsWhiteSpace(cs))
- .HandleWith(new WordLexerState());
-
- _allLineContentLexer = builder.Build();
- }
-
public static string NativeDirectiveName => "native";
public static string StackRuntimeDirectiveName => "stack";
-
- protected override bool DirectiveSupported(string directive)
- {
- return string.Equals(directive, NativeDirectiveName, StringComparison.CurrentCultureIgnoreCase) ||
- string.Equals(directive, StackRuntimeDirectiveName, StringComparison.CurrentCultureIgnoreCase);
- }
- protected override void ParseAnnotationInternal(ref Lexem lastExtractedLexem, ILexer lexer, ParserContext parserContext)
+ private static readonly HashSet Directives = new HashSet
+ {
+ NativeDirectiveName,
+ StackRuntimeDirectiveName
+ };
+
+ public NativeRuntimeAnnotationHandler(IErrorSink errorSink) : base(Directives, errorSink)
{
- var node = new AnnotationNode(NodeKind.Annotation, lastExtractedLexem);
- _allLineContentLexer.Iterator = lexer.Iterator;
-
- parserContext.AddChild(node);
-
- // после ничего не должно находиться
- var nextLexem = _allLineContentLexer.NextLexemOnSameLine();
- lastExtractedLexem = lexer.NextLexem(); // сдвиг основного лексера
- if (nextLexem.Type != LexemType.EndOfText)
- {
- var err = LocalizedErrors.ExpressionSyntax();
- err.Position = new ErrorPositionInfo
- {
- LineNumber = node.Location.LineNumber,
- ColumnNumber = node.Location.ColumnNumber,
- Code = lexer.Iterator.GetCodeLine(node.Location.LineNumber),
- ModuleName = lexer.Iterator.Source.Name
- };
- ErrorSink.AddError(err);
- }
}
}
}
\ No newline at end of file
diff --git a/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs b/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs
index 07321e0a3..0eadcb418 100644
--- a/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs
+++ b/src/OneScript.StandardLibrary/Binary/BinaryDataBuffer.cs
@@ -11,6 +11,7 @@ This Source Code Form is subject to the terms of the
using OneScript.Commons;
using OneScript.Contexts;
using OneScript.Exceptions;
+using OneScript.StandardLibrary.Collections;
using OneScript.Types;
using ScriptEngine.Machine;
using ScriptEngine.Machine.Contexts;
@@ -29,21 +30,15 @@ namespace OneScript.StandardLibrary.Binary
[ContextClass("БуферДвоичныхДанных", "BinaryDataBuffer")]
public class BinaryDataBuffer : AutoCollectionContext
{
- private bool _readOnly;
- private readonly byte[] _buffer;
-
public BinaryDataBuffer(byte[] buffer, ByteOrderEnum byteOrder = ByteOrderEnum.LittleEndian)
{
- _buffer = buffer;
+ Bytes = buffer;
ByteOrder = byteOrder;
}
// для операций с содержимым буфера внутри 1Script
//
- public byte[] Bytes
- {
- get { return _buffer; }
- }
+ public byte[] Bytes { get; }
///
/// Размер буфера в байтах.
@@ -75,7 +70,7 @@ public override void SetIndexedValue(IValue index, IValue val)
throw RuntimeException.InvalidArgumentValue();
var idx = (int)index.AsNumber();
- _buffer[idx] = (byte) value;
+ Bytes[idx] = (byte) value;
}
///
@@ -92,7 +87,7 @@ public override void SetIndexedValue(IValue index, IValue val)
///
/// Число (Number)
[ContextProperty("Размер", "Size")]
- public long Size => _buffer.LongLength;
+ public long Size => Bytes.LongLength;
///
///
@@ -100,11 +95,7 @@ public override void SetIndexedValue(IValue index, IValue val)
///
/// Булево (Boolean)
[ContextProperty("ТолькоЧтение", "ReadOnly")]
- public bool ReadOnly
- {
- get { return _readOnly; }
-
- }
+ public bool ReadOnly { get; private set; }
///
///
@@ -124,9 +115,9 @@ public void Write(int position, BinaryDataBuffer bytes, int number = 0)
ThrowIfReadonly();
if (number == 0)
- Array.Copy(bytes._buffer, 0, _buffer, position, bytes._buffer.Length);
+ Array.Copy(bytes.Bytes, 0, Bytes, position, bytes.Bytes.Length);
else
- Array.Copy(bytes._buffer, 0, _buffer, position, number);
+ Array.Copy(bytes.Bytes, 0, Bytes, position, number);
}
private byte[] GetBytes(T value, Converter leConverter, Converter beConverter, IValue byteOrder = null)
@@ -158,7 +149,7 @@ private void CopyBytes(int position, byte[] bytes)
{
for (int i = 0; i < bytes.Length; i++)
{
- _buffer[position + i] = bytes[i];
+ Bytes[position + i] = bytes[i];
}
}
@@ -258,9 +249,9 @@ private void WriteBitwiseOp(int position, BinaryDataBuffer buffer, int number, F
try
{
- var bytesToCopy = (number == 0 ? buffer._buffer.Length : number);
+ var bytesToCopy = (number == 0 ? buffer.Bytes.Length : number);
for (int i = 0; i < bytesToCopy; i++)
- _buffer[i + position] = op(_buffer[i + position], buffer._buffer[i]);
+ Bytes[i + position] = op(Bytes[i + position], buffer.Bytes[i]);
}
catch (IndexOutOfRangeException)
{
@@ -363,7 +354,7 @@ public void WriteBitwiseXor(int position, BinaryDataBuffer bytes, int number = 0
[ContextMethod("Перевернуть", "Reverse")]
public BinaryDataBuffer Reverse()
{
- var bytes = _buffer.Reverse().ToArray();
+ var bytes = Bytes.Reverse().ToArray();
return new BinaryDataBuffer(bytes, ByteOrder);
}
@@ -384,7 +375,7 @@ public BinaryDataBuffer Reverse()
[ContextMethod("Получить", "Get")]
public int Get(int position)
{
- return _buffer[position];
+ return Bytes[position];
}
@@ -427,7 +418,7 @@ public BinaryDataBuffer GetSlice(int position, IValue number = null)
public BinaryDataBuffer Read(int position, int number)
{
var data = new byte[number];
- Array.Copy(_buffer, position, data, 0, number);
+ Array.Copy(Bytes, position, data, 0, number);
return new BinaryDataBuffer(data, ByteOrder);
}
@@ -453,7 +444,7 @@ private T FromBytes(int position, Func leConverter, Func
@@ -540,11 +531,113 @@ public ulong ReadInt64(int position, IValue byteOrder = null)
///
///
[ContextMethod("Разделить", "Split")]
- public IValue Split(IValue separator)
+ public ArrayImpl Split(IValue separator)
{
- throw new NotImplementedException();
+ var buffers = ParseParam(separator);
+
+ // Функция поиска требует, чтобы буферы были в порядке убывания размера
+ buffers.Sort((a, b) => b.Bytes.LongLength.CompareTo(a.Bytes.LongLength));
+ return SplitBuffer(buffers.ToArray());
+ }
+
+ private static List ParseParam(IValue separator)
+ {
+ var rawSeparator = separator?.GetRawValue();
+ switch (rawSeparator)
+ {
+ case BinaryDataBuffer buffer:
+ return new List { CheckedBuffer(buffer) };
+
+ case ArrayImpl array:
+ {
+ var buffers = new List();
+
+ foreach (var element in array)
+ {
+ buffers.AddRange(ParseParam(element));
+ }
+
+ return buffers;
+ }
+
+ default:
+ throw RuntimeException.InvalidArgumentType();
+ }
+ }
+
+ private static BinaryDataBuffer CheckedBuffer(BinaryDataBuffer buffer)
+ {
+ if (buffer.Size == 0)
+ {
+ throw RuntimeException.InvalidArgumentValue();
+ }
+
+ return buffer;
+ }
+
+ private ArrayImpl SplitBuffer(BinaryDataBuffer[] splitter)
+ {
+ var result = new List();
+ long start = 0;
+ var foundPosition = FindFirst(splitter, start);
+ while (foundPosition.pos != -1)
+ {
+ var length = foundPosition.pos - start;
+ result.Add(new BinaryDataBuffer(Copy(start, length), ByteOrder));
+ start = foundPosition.pos + foundPosition.buffer.Size;
+ foundPosition = FindFirst(splitter, start);
+ }
+
+ // хвостовой элемент
+ result.Add(new BinaryDataBuffer(Copy(start, Bytes.LongLength - start)));
+ return new ArrayImpl(result);
}
+ ///
+ /// Ищет ближайшее вхождение любого из буферов. Если на одной позиции находятся два и более буфера, берется бОльший.
+ ///
+ /// Массив искомых буферов
+ /// Начальная позиция поиска
+ /// Буфер и позиция или null, если нет вхождений
+ private (BinaryDataBuffer buffer, long pos) FindFirst(BinaryDataBuffer[] buffers, long start)
+ {
+ var maxI = Size - buffers[buffers.Length - 1].Size;
+ for (var i = start; i < maxI; i++)
+ {
+ foreach (var expectedBuffer in buffers)
+ {
+ if (SubsequenceEquals(Bytes, i, expectedBuffer.Bytes))
+ {
+ return (expectedBuffer, i);
+ }
+ }
+ }
+
+ return (null, -1);
+ }
+
+ private byte[] Copy(long start, long length)
+ {
+ if (length == 0) return Array.Empty();
+ var partition = new byte[length];
+ Array.Copy(Bytes, start, partition, 0, length);
+ return partition;
+ }
+
+ private static bool SubsequenceEquals(byte[] sequence, long start, byte[] subsequence)
+ {
+ for (long j = 0; j < subsequence.LongLength; j++)
+ {
+ if (subsequence[j] != sequence[start + j])
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
///
///
/// Создает копию массива.
@@ -556,8 +649,8 @@ public IValue Split(IValue separator)
[ContextMethod("Скопировать", "Copy")]
public BinaryDataBuffer Copy()
{
- byte[] copy = new byte[_buffer.Length];
- Array.Copy(_buffer, copy, _buffer.Length);
+ byte[] copy = new byte[Bytes.Length];
+ Array.Copy(Bytes, copy, Bytes.Length);
return new BinaryDataBuffer(copy, ByteOrder);
}
@@ -575,11 +668,11 @@ public BinaryDataBuffer Copy()
[ContextMethod("Соединить", "Concat")]
public BinaryDataBuffer Concat(BinaryDataBuffer buffer)
{
- var source = buffer._buffer;
- var totalLength = _buffer.Length + source.Length;
+ var source = buffer.Bytes;
+ var totalLength = Bytes.Length + source.Length;
var joinedArray = new byte[totalLength];
- Array.Copy(_buffer, joinedArray, _buffer.Length);
- Array.Copy(source, 0, joinedArray, _buffer.Length, source.Length);
+ Array.Copy(Bytes, joinedArray, Bytes.Length);
+ Array.Copy(source, 0, joinedArray, Bytes.Length, source.Length);
return new BinaryDataBuffer(joinedArray, ByteOrder);
}
@@ -600,7 +693,7 @@ public void Set(int position, IValue value)
{
ThrowIfReadonly();
- _buffer[position] = (byte)AsUnsignedLong(value, byte.MaxValue);
+ Bytes[position] = (byte)AsUnsignedLong(value, byte.MaxValue);
}
@@ -617,25 +710,25 @@ public void Set(int position, IValue value)
[ContextMethod("УстановитьТолькоЧтение", "SetReadOnly")]
public void SetReadOnly()
{
- _readOnly = true;
+ ReadOnly = true;
}
public override int Count()
{
- return _buffer.Length;
+ return Bytes.Length;
}
public override IEnumerator GetEnumerator()
{
- for (long i = 0; i < _buffer.LongLength; i++)
+ for (long i = 0; i < Bytes.LongLength; i++)
{
- yield return ValueFactory.Create(_buffer[i]);
+ yield return ValueFactory.Create(Bytes[i]);
}
}
public void ThrowIfReadonly()
{
- if (_readOnly)
+ if (ReadOnly)
throw new RuntimeException("Буфер находится в режиме \"Только чтение\"");
}
}
diff --git a/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs b/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs
index 458cdd030..04a29e00f 100644
--- a/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs
+++ b/src/OneScript.StandardLibrary/Binary/GlobalBinaryData.cs
@@ -21,7 +21,7 @@ namespace OneScript.StandardLibrary.Binary
[GlobalContext(Category = "Процедуры и функции работы с двоичными данными")]
public sealed class GlobalBinaryData : GlobalContextBase
{
- private static byte[] HexStringToByteArray(String hex)
+ private static byte[] HexStringToByteArray(string hex)
{
var newHex = System.Text.RegularExpressions.Regex.Replace(hex, @"[^0-9A-Fa-f]", "");
int numberChars = newHex.Length;
@@ -130,6 +130,17 @@ private static string GetStringFromByteBuffer(byte[] buf, Encoding enc)
return enc.GetString(buf, startPos, buf.Length - startPos);
}
+ private static void CheckAndThrowIfNull(AutoContext obj) where T : AutoContext
+ {
+ if (obj == null)
+ throw RuntimeException.InvalidArgumentType();
+ }
+
+ private static void CheckAndThrowIfNull(AutoContext obj, int argNumber, string argName) where T : AutoContext
+ {
+ if (obj == null)
+ throw RuntimeException.InvalidArgumentType(argNumber, argName);
+ }
public static IAttachableContext CreateInstance()
{
@@ -150,19 +161,19 @@ public static IAttachableContext CreateInstance()
[ContextMethod("СоединитьДвоичныеДанные")]
public BinaryDataContext ConcatenateBinaryData(ArrayImpl array)
{
+ CheckAndThrowIfNull(array);
+
// Сделано на int т.к. BinaryContext.Size имеет тип int;
+ using var stream = new System.IO.MemoryStream();
- using (var stream = new System.IO.MemoryStream())
+ foreach (var cbd in array)
{
-
- foreach (var cbd in array)
- {
- byte[] buffer = ((BinaryDataContext) cbd.AsObject()).Buffer;
- stream.Write(buffer, 0, buffer.Length);
- }
- stream.Position = 0;
- return new BinaryDataContext(stream);
+ byte[] buffer = ((BinaryDataContext)cbd.AsObject()).Buffer;
+ stream.Write(buffer, 0, buffer.Length);
}
+ stream.Position = 0;
+
+ return new BinaryDataContext(stream);
}
///
@@ -174,6 +185,8 @@ public BinaryDataContext ConcatenateBinaryData(ArrayImpl array)
[ContextMethod("РазделитьДвоичныеДанные")]
public ArrayImpl SplitBinaryData(BinaryDataContext data, long size)
{
+ CheckAndThrowIfNull(data, 1, nameof(data));
+
if (size <= 0 || size > Int32.MaxValue)
throw RuntimeException.InvalidNthArgumentValue(2);
@@ -257,9 +270,10 @@ public BinaryDataBuffer GetBinaryDataBufferFromString(string str, IValue encodin
[ContextMethod("ПолучитьСтрокуИзДвоичныхДанных")]
public string GetStringFromBinaryData(BinaryDataContext data, IValue encoding = null)
{
+ CheckAndThrowIfNull(data, 1, nameof(data));
+
// Получаем кодировку
// Из синтаксис помощника если кодировка не задана используем UTF8
-
var enc = (encoding != null) ? TextEncodingEnum.GetEncoding(encoding) : Encoding.UTF8;
return GetStringFromByteBuffer(data.Buffer, enc);
@@ -274,6 +288,8 @@ public string GetStringFromBinaryData(BinaryDataContext data, IValue encoding =
[ContextMethod("ПолучитьСтрокуИзБуфераДвоичныхДанных")]
public string GetStringFromBinaryDataBuffer(BinaryDataBuffer buffer, IValue encoding = null)
{
+ CheckAndThrowIfNull(buffer, 1, nameof(buffer));
+
var enc = (encoding != null) ? TextEncodingEnum.GetEncoding(encoding) : Encoding.UTF8;
return GetStringFromByteBuffer(buffer.Bytes, enc);
@@ -325,6 +341,8 @@ public BinaryDataBuffer GetBinaryDataBufferFromBase64String(string str)
[ContextMethod("ПолучитьBase64СтрокуИзДвоичныхДанных")]
public string GetBase64StringFromBinaryData(BinaryDataContext data)
{
+ CheckAndThrowIfNull(data, 1, nameof(data));
+
return Convert.ToBase64String(data.Buffer, Base64FormattingOptions.InsertLineBreaks);
}
@@ -338,6 +356,8 @@ public string GetBase64StringFromBinaryData(BinaryDataContext data)
[ContextMethod("ПолучитьBase64СтрокуИзБуфераДвоичныхДанных")]
public string GetBase64StringFromBinaryDataBuffer(BinaryDataBuffer buffer)
{
+ CheckAndThrowIfNull(buffer);
+
return Convert.ToBase64String(buffer.Bytes, Base64FormattingOptions.InsertLineBreaks);
}
@@ -349,6 +369,8 @@ public string GetBase64StringFromBinaryDataBuffer(BinaryDataBuffer buffer)
[ContextMethod("ПолучитьДвоичныеДанныеИзBase64ДвоичныхДанных")]
public BinaryDataContext GetBinaryDataFromBase64BinaryData(BinaryDataContext data)
{
+ CheckAndThrowIfNull(data);
+
try
{
var enc = new UTF8Encoding(false,true);
@@ -369,6 +391,8 @@ public BinaryDataContext GetBinaryDataFromBase64BinaryData(BinaryDataContext dat
[ContextMethod("ПолучитьБуферДвоичныхДанныхИзBase64БуфераДвоичныхДанных")]
public BinaryDataBuffer GetBinaryDataBufferFromBase64BinaryDataBuffer(BinaryDataBuffer buffer)
{
+ CheckAndThrowIfNull(buffer);
+
try
{
var enc = new UTF8Encoding(false, true);
@@ -391,6 +415,8 @@ public BinaryDataBuffer GetBinaryDataBufferFromBase64BinaryDataBuffer(BinaryData
[ContextMethod("ПолучитьBase64ДвоичныеДанныеИзДвоичныхДанных")]
public BinaryDataContext GetBase64BinaryDataFromBinaryData(BinaryDataContext data)
{
+ CheckAndThrowIfNull(data);
+
var base64str = Convert.ToBase64String(data.Buffer, Base64FormattingOptions.InsertLineBreaks);
return new BinaryDataContext(Encoding.ASCII.GetBytes(base64str));
}
@@ -405,6 +431,8 @@ public BinaryDataContext GetBase64BinaryDataFromBinaryData(BinaryDataContext dat
[ContextMethod("ПолучитьBase64БуферДвоичныхДанныхИзБуфераДвоичныхДанных")]
public BinaryDataBuffer GetBase64BinaryDataBufferFromBinaryDataBuffer(BinaryDataBuffer buffer)
{
+ CheckAndThrowIfNull(buffer);
+
var base64str = Convert.ToBase64String(buffer.Bytes, Base64FormattingOptions.InsertLineBreaks);
return new BinaryDataBuffer(Encoding.ASCII.GetBytes(base64str));
}
@@ -439,6 +467,8 @@ public BinaryDataBuffer GetBinaryDataBufferFromHexString(string hex)
[ContextMethod("ПолучитьHexСтрокуИзДвоичныхДанных")]
public string GetHexStringFromBinaryData(BinaryDataContext data)
{
+ CheckAndThrowIfNull(data);
+
return BitConverter.ToString(data.Buffer).Replace("-","");
}
@@ -450,6 +480,8 @@ public string GetHexStringFromBinaryData(BinaryDataContext data)
[ContextMethod("ПолучитьHexСтрокуИзБуфераДвоичныхДанных")]
public string GetHexStringFromBinaryDataBuffer(BinaryDataBuffer buffer)
{
+ CheckAndThrowIfNull(buffer);
+
return BitConverter.ToString(buffer.Bytes).Replace("-","");
}
@@ -461,6 +493,8 @@ public string GetHexStringFromBinaryDataBuffer(BinaryDataBuffer buffer)
[ContextMethod("ПолучитьДвоичныеДанныеИзHexДвоичныхДанных")]
public BinaryDataContext GetBinaryDataFromHexBinaryData(BinaryDataContext data)
{
+ CheckAndThrowIfNull(data);
+
return new BinaryDataContext(HexArrayToByteArray(data.Buffer));
}
@@ -472,6 +506,8 @@ public BinaryDataContext GetBinaryDataFromHexBinaryData(BinaryDataContext data)
[ContextMethod("ПолучитьБуферДвоичныхДанныхИзHexБуфераДвоичныхДанных")]
public BinaryDataBuffer GetBinaryDataBufferFromHexBinaryDataBuffer(BinaryDataBuffer buffer)
{
+ CheckAndThrowIfNull(buffer);
+
return new BinaryDataBuffer(HexArrayToByteArray(buffer.Bytes));
}
@@ -507,6 +543,8 @@ public BinaryDataBuffer GetHexBinaryDataBufferFromBinaryDataBuffer(BinaryDataBuf
[ContextMethod("ПолучитьБуферДвоичныхДанныхИзДвоичныхДанных")]
public BinaryDataBuffer GetBinaryDataBufferFromBinaryData(BinaryDataContext data)
{
+ CheckAndThrowIfNull(data);
+
return new BinaryDataBuffer(data.Buffer);
}
@@ -518,6 +556,8 @@ public BinaryDataBuffer GetBinaryDataBufferFromBinaryData(BinaryDataContext data
[ContextMethod("ПолучитьДвоичныеДанныеИзБуфераДвоичныхДанных")]
public BinaryDataContext GetBinaryDataFromBinaryDataBuffer(BinaryDataBuffer buffer)
{
+ CheckAndThrowIfNull(buffer);
+
return new BinaryDataContext(buffer.Bytes);
}
diff --git a/src/OneScript.StandardLibrary/Collections/Indexes/CollectionIndex.cs b/src/OneScript.StandardLibrary/Collections/Indexes/CollectionIndex.cs
new file mode 100644
index 000000000..e1ff63ab8
--- /dev/null
+++ b/src/OneScript.StandardLibrary/Collections/Indexes/CollectionIndex.cs
@@ -0,0 +1,134 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using OneScript.Commons;
+using OneScript.Contexts;
+using OneScript.Exceptions;
+using OneScript.Types;
+using OneScript.Values;
+using ScriptEngine.Machine;
+using ScriptEngine.Machine.Contexts;
+using ScriptEngine.Types;
+
+namespace OneScript.StandardLibrary.Collections.Indexes
+{
+ [ContextClass("ИндексКоллекции", "CollectionIndex", TypeUUID = "48D150D4-A0DA-47CA-AEA3-D4078A731C11")]
+ public class CollectionIndex : AutoCollectionContext
+ {
+ private static readonly TypeDescriptor _objectType = typeof(CollectionIndex).GetTypeFromClassMarkup();
+
+ private readonly List _fields = new List();
+ private readonly IIndexCollectionSource _source;
+
+ private readonly IDictionary> _data =
+ new Dictionary>();
+
+ public CollectionIndex(IIndexCollectionSource source, IEnumerable fields) : base(_objectType)
+ {
+ _source = source;
+ _fields.AddRange(fields);
+ }
+
+ internal bool CanBeUsedFor(IEnumerable searchFields)
+ {
+ return _fields.Any() && _fields.ToHashSet().IsSubsetOf(searchFields.ToHashSet());
+ }
+
+ private CollectionIndexKey IndexKey(PropertyNameIndexAccessor source)
+ {
+ return CollectionIndexKey.Extract(source, _fields);
+ }
+
+ public override string ToString()
+ {
+ return string.Join(", ", _fields.Select(field => _source.GetName(field)));
+ }
+
+ public IEnumerable GetData(PropertyNameIndexAccessor searchCriteria)
+ {
+ var key = IndexKey(searchCriteria);
+ return _data.TryGetValue(key, out var filteredData) ? filteredData : new List();
+ }
+
+ internal void FieldRemoved(IValue field)
+ {
+ if (_fields.Contains(field))
+ {
+ while (_fields.Contains(field)) _fields.Remove(field);
+ Rebuild();
+ }
+ }
+
+ internal void ElementAdded(PropertyNameIndexAccessor element)
+ {
+ var key = CollectionIndexKey.Extract(element, _fields);
+ if (_data.TryGetValue(key, out var list))
+ {
+ list.Add(element);
+ }
+ else
+ {
+ _data.Add(key, new List { element});
+ }
+ }
+
+ internal void ElementRemoved(PropertyNameIndexAccessor element)
+ {
+ var key = CollectionIndexKey.Extract(element, _fields);
+ if (_data.TryGetValue(key, out var value))
+ {
+ value.Remove(element);
+ }
+ }
+
+ internal void Clear()
+ {
+ _data.Clear();
+ }
+
+ internal void Rebuild()
+ {
+ _data.Clear();
+ foreach (var value in _source)
+ {
+ ElementAdded(value);
+ }
+ }
+
+ public override IValue GetIndexedValue(IValue index)
+ {
+ var rawValue = index.GetRawValue();
+ if (rawValue is BslNumericValue numericValue)
+ {
+ var numeric = numericValue.AsNumber();
+ if (numeric >= 0 && numeric < _fields.Count)
+ {
+
+ return ValueFactory.Create(_source.GetName(_fields[decimal.ToInt32(numeric)]));
+ }
+ }
+ throw RuntimeException.InvalidArgumentValue();
+ }
+
+ public override int Count()
+ {
+ return _fields.Count;
+ }
+
+ public override IEnumerator GetEnumerator()
+ {
+ foreach (var field in _fields)
+ {
+ yield return ValueFactory.Create(_source.GetName(field));
+ }
+ }
+ }
+}
diff --git a/src/OneScript.StandardLibrary/Collections/Indexes/CollectionIndexKey.cs b/src/OneScript.StandardLibrary/Collections/Indexes/CollectionIndexKey.cs
new file mode 100644
index 000000000..e33a9090b
--- /dev/null
+++ b/src/OneScript.StandardLibrary/Collections/Indexes/CollectionIndexKey.cs
@@ -0,0 +1,84 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System.Collections.Generic;
+using System.Linq;
+using ScriptEngine.Machine;
+using ScriptEngine.Machine.Contexts;
+
+namespace OneScript.StandardLibrary.Collections.Indexes
+{
+ public class CollectionIndexKey
+ {
+ private readonly IDictionary _values;
+ private readonly int _hashCode;
+
+ private CollectionIndexKey(IDictionary values)
+ {
+ _values = values;
+ _hashCode = EvalHashCode(values.Values);
+ }
+
+ private static int EvalHashCode(IEnumerable values)
+ {
+ var result = 0;
+ foreach (var value in values)
+ {
+ result ^= value.GetHashCode();
+ }
+
+ return result;
+ }
+
+ public static CollectionIndexKey Extract(PropertyNameIndexAccessor source, IEnumerable fields)
+ {
+ var values = new Dictionary();
+
+ foreach (var field in fields)
+ {
+ var value = source.GetIndexedValue(field);
+ values.TryAdd(field, value);
+ }
+
+ return new CollectionIndexKey(values);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (object.ReferenceEquals(this, obj)) return true;
+ if (obj is CollectionIndexKey casted)
+ {
+ var allKeys = CombinedKeysSet(casted);
+
+ foreach (var key in allKeys)
+ {
+ var thisValue = _values[key];
+ var otherValue = _values[key];
+
+ if (!thisValue.Equals(otherValue)) return false;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return _hashCode;
+ }
+
+ private ISet CombinedKeysSet(CollectionIndexKey other)
+ {
+ var allKeys = new HashSet();
+ allKeys.UnionWith(_values.Keys.ToHashSet());
+ allKeys.UnionWith(other._values.Keys.ToHashSet());
+ return allKeys;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.StandardLibrary/Collections/Indexes/IIndexCollectionSource.cs b/src/OneScript.StandardLibrary/Collections/Indexes/IIndexCollectionSource.cs
new file mode 100644
index 000000000..9ffd3d8f3
--- /dev/null
+++ b/src/OneScript.StandardLibrary/Collections/Indexes/IIndexCollectionSource.cs
@@ -0,0 +1,30 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using OneScript.Contexts;
+using ScriptEngine.Machine;
+using ScriptEngine.Machine.Contexts;
+
+namespace OneScript.StandardLibrary.Collections.Indexes
+{
+ public interface IIndexCollectionSource : ICollectionContext
+ {
+ ///
+ /// Возвращает имя поля
+ ///
+ /// Поле
+ /// Строка. Имя поля
+ string GetName(IValue field);
+
+ ///
+ /// Возвращает поле по имени.
+ ///
+ /// Имя поля
+ /// Поле
+ IValue GetField(string name);
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.StandardLibrary/Collections/MapImpl.cs b/src/OneScript.StandardLibrary/Collections/MapImpl.cs
index 4ba66aae1..5e0cb9956 100644
--- a/src/OneScript.StandardLibrary/Collections/MapImpl.cs
+++ b/src/OneScript.StandardLibrary/Collections/MapImpl.cs
@@ -73,6 +73,14 @@ internal bool ContainsKey(IValue key)
return _content.ContainsKey(key);
}
+ public IEnumerable Keys()
+ {
+ foreach (var key in _content.Keys)
+ {
+ yield return key;
+ }
+ }
+
#region ICollectionContext Members
[ContextMethod("Вставить", "Insert")]
diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs
index 090e757d8..c1f82f98c 100644
--- a/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs
+++ b/src/OneScript.StandardLibrary/Collections/ValueTable/CollectionIndexes.cs
@@ -9,7 +9,10 @@ This Source Code Form is subject to the terms of the
using System.Collections.Generic;
using System.Linq;
using OneScript.Contexts;
+using OneScript.Exceptions;
+using OneScript.StandardLibrary.Collections.Indexes;
using OneScript.Types;
+using OneScript.Values;
using ScriptEngine.Machine;
using ScriptEngine.Machine.Contexts;
using ScriptEngine.Types;
@@ -22,15 +25,18 @@ public class CollectionIndexes : AutoCollectionContext _indexes = new List();
+ private readonly IIndexCollectionSource _owner;
- public CollectionIndexes() : base(_instanceType)
+ public CollectionIndexes(IIndexCollectionSource owner) : base(_instanceType)
{
+ _owner = owner;
}
[ContextMethod("Добавить", "Add")]
public CollectionIndex Add(string columns)
{
- CollectionIndex newIndex = new CollectionIndex();
+ var newIndex = new CollectionIndex(_owner, BuildFieldList(_owner, columns));
+ newIndex.Rebuild();
_indexes.Add(newIndex);
return newIndex;
}
@@ -42,13 +48,9 @@ public override int Count()
}
[ContextMethod("Удалить", "Delete")]
- public void Delete(IValue Index)
+ public void Delete(IValue index)
{
- Index = Index.GetRawValue();
- if (Index is CollectionIndex)
- _indexes.Remove(Index as CollectionIndex);
- else
- _indexes.RemoveAt(Decimal.ToInt32(Index.AsNumber()));
+ _indexes.Remove(GetIndex(index));
}
[ContextMethod("Очистить", "Clear")]
@@ -57,6 +59,102 @@ public void Clear()
_indexes.Clear();
}
+ public override IValue GetIndexedValue(IValue index)
+ {
+ return GetIndex(index);
+ }
+
+ private CollectionIndex GetIndex(IValue index)
+ {
+ index = index.GetRawValue();
+ if (index is CollectionIndex collectionIndex)
+ {
+ if (_indexes.Contains(collectionIndex))
+ {
+ return collectionIndex;
+ }
+ throw RuntimeException.InvalidArgumentValue();
+ }
+
+ if (index is BslNumericValue numberValue)
+ {
+ var number = numberValue.AsNumber();
+ if (number >= 0 && number < _indexes.Count)
+ {
+ return _indexes[decimal.ToInt32(number)];
+ }
+
+ throw RuntimeException.InvalidArgumentValue();
+ }
+
+ throw RuntimeException.InvalidArgumentType();
+ }
+
+ public void Rebuild()
+ {
+ foreach (var index in _indexes)
+ {
+ index.Rebuild();
+ }
+ }
+
+ internal void ClearIndexes()
+ {
+ foreach (var index in _indexes)
+ {
+ index.Clear();
+ }
+ }
+
+ internal void FieldRemoved(IValue field)
+ {
+ foreach (var index in _indexes)
+ {
+ index.FieldRemoved(field);
+ }
+ }
+
+ internal void ElementAdded(PropertyNameIndexAccessor element)
+ {
+ foreach (var index in _indexes)
+ {
+ index.ElementAdded(element);
+ }
+ }
+
+ internal void ElementRemoved(PropertyNameIndexAccessor element)
+ {
+ foreach (var index in _indexes)
+ {
+ index.ElementRemoved(element);
+ }
+ }
+
+ public CollectionIndex FindSuitableIndex(IEnumerable searchFields)
+ {
+ return _indexes.FirstOrDefault(index => index.CanBeUsedFor(searchFields));
+ }
+
+ private static IList BuildFieldList(IIndexCollectionSource source, string fieldList)
+ {
+ var fields = new List();
+ var fieldNames = fieldList.Split(',');
+ foreach (var fieldName in fieldNames)
+ {
+ if (!string.IsNullOrWhiteSpace(fieldName))
+ {
+ var field = source.GetField(fieldName.Trim());
+ if (field == null)
+ {
+ throw new ColumnNotFoundException(fieldName);
+ }
+ fields.Add(field);
+ }
+ }
+
+ return fields;
+ }
+
public override IEnumerator GetEnumerator()
{
foreach (var item in _indexes)
diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ColumnNotFoundException.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ColumnNotFoundException.cs
new file mode 100644
index 000000000..84d11bffe
--- /dev/null
+++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ColumnNotFoundException.cs
@@ -0,0 +1,29 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+using System;
+using OneScript.Exceptions;
+using OneScript.Localization;
+
+namespace OneScript.StandardLibrary.Collections.ValueTable
+{
+ public class ColumnNotFoundException : RuntimeException
+ {
+ public ColumnNotFoundException(BilingualString message, Exception innerException) : base(message,
+ innerException)
+ {
+ }
+
+ public ColumnNotFoundException(BilingualString message) : base(message)
+ {
+ }
+
+ public ColumnNotFoundException(string columnName) : base($"Неверное имя колонки {columnName}")
+ {
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs
index eb52b0a8f..4c1239d4c 100644
--- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs
+++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTable.cs
@@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the
using System.Collections.Generic;
using System.Linq;
using OneScript.Contexts;
+using OneScript.StandardLibrary.Collections.Indexes;
using OneScript.Exceptions;
using OneScript.Types;
using ScriptEngine.Machine;
@@ -21,17 +22,15 @@ namespace OneScript.StandardLibrary.Collections.ValueTable
/// Представляет из себя коллекцию строк с заранее заданной структурой.
///
[ContextClass("ТаблицаЗначений", "ValueTable")]
- public class ValueTable : AutoCollectionContext
+ public class ValueTable : AutoCollectionContext, IIndexCollectionSource
{
- private readonly ValueTableColumnCollection _columns;
private readonly List _rows;
- private readonly CollectionIndexes _indexes;
public ValueTable()
{
- _columns = new ValueTableColumnCollection(this);
+ Columns = new ValueTableColumnCollection(this);
_rows = new List();
- _indexes = new CollectionIndexes();
+ Indexes = new CollectionIndexes(this);
}
///
@@ -39,20 +38,14 @@ public ValueTable()
///
/// КоллекцияКолонокТаблицыЗначений
[ContextProperty("Колонки", "Columns")]
- public ValueTableColumnCollection Columns
- {
- get { return _columns; }
- }
+ public ValueTableColumnCollection Columns { get; }
///
/// Коллекция индексов
///
/// ИндексыКоллекции
[ContextProperty("Индексы", "Indexes")]
- public CollectionIndexes Indexes
- {
- get { return _indexes; }
- }
+ public CollectionIndexes Indexes { get; }
///
/// Количество строк в Таблице значений
@@ -71,8 +64,9 @@ public override int Count()
[ContextMethod("Добавить", "Add")]
public ValueTableRow Add()
{
- ValueTableRow row = new ValueTableRow(this);
+ var row = new ValueTableRow(this);
_rows.Add(row);
+ Indexes.ElementAdded(row);
return row;
}
@@ -84,8 +78,9 @@ public ValueTableRow Add()
[ContextMethod("Вставить", "Insert")]
public ValueTableRow Insert(int index)
{
- ValueTableRow row = new ValueTableRow(this);
+ var row = new ValueTableRow(this);
_rows.Insert(index, row);
+ Indexes.ElementAdded(row);
return row;
}
@@ -99,8 +94,8 @@ public ValueTableRow Insert(int index)
[ContextMethod("Удалить", "Delete")]
public void Delete(IValue row)
{
- int index = IndexByValue(row);
-
+ var index = IndexByValue(row);
+ Indexes.ElementRemoved(_rows[index]);
_rows.RemoveAt(index);
}
@@ -120,10 +115,14 @@ public void LoadColumn(IValue values, IValue columnIndex)
var row_iterator = _rows.GetEnumerator();
var array_iterator = (values as ArrayImpl).GetEnumerator();
+ Indexes.ClearIndexes();
+
while (row_iterator.MoveNext() && array_iterator.MoveNext())
{
row_iterator.Current.Set(columnIndex, array_iterator.Current);
}
+
+ Indexes.Rebuild();
}
///
@@ -138,9 +137,9 @@ public void LoadColumn(IValue values, IValue columnIndex)
[ContextMethod("ВыгрузитьКолонку", "UnloadColumn")]
public ArrayImpl UnloadColumn(IValue column)
{
- ArrayImpl result = new ArrayImpl();
+ var result = new ArrayImpl();
- foreach (ValueTableRow row in _rows)
+ foreach (var row in _rows)
{
result.Add(row.Get(column));
}
@@ -159,10 +158,10 @@ private List GetProcessingColumnList(string ColumnNames, bool
return processing_list;
}
- foreach (string column_name in ColumnNames.Split(','))
+ foreach (var column_name in ColumnNames.Split(','))
{
- string name = column_name.Trim();
- ValueTableColumn Column = Columns.FindColumnByName(name);
+ var name = column_name.Trim();
+ var Column = Columns.FindColumnByName(name);
if (Column == null)
throw WrongColumnNameException(name);
@@ -173,8 +172,7 @@ private List GetProcessingColumnList(string ColumnNames, bool
}
else if (!EmptyListInCaseOfNull)
{
- foreach (ValueTableColumn Column in _columns)
- processing_list.Add(Column);
+ processing_list.AddRange(Columns);
}
return processing_list;
}
@@ -187,14 +185,16 @@ private List GetProcessingColumnList(string ColumnNames, bool
[ContextMethod("ЗаполнитьЗначения", "FillValues")]
public void FillValues(IValue value, string columnNames = null)
{
- List processing_list = GetProcessingColumnList(columnNames);
- foreach (ValueTableRow row in _rows)
+ var processing_list = GetProcessingColumnList(columnNames);
+ Indexes.ClearIndexes();
+ foreach (var row in _rows)
{
- foreach (ValueTableColumn col in processing_list)
+ foreach (var col in processing_list)
{
row.Set(col, value);
}
}
+ Indexes.Rebuild();
}
///
@@ -207,8 +207,8 @@ public int IndexOf(IValue row)
{
row = row.GetRawValue();
- if (row is ValueTableRow)
- return _rows.IndexOf(row as ValueTableRow);
+ if (row is ValueTableRow tableRow)
+ return _rows.IndexOf(tableRow);
return -1;
}
@@ -225,13 +225,13 @@ public int IndexOf(IValue row)
[ContextMethod("Итог", "Total")]
public IValue Total(IValue columnIndex)
{
- ValueTableColumn Column = Columns.GetColumnByIIndex(columnIndex);
+ var Column = Columns.GetColumnByIIndex(columnIndex);
bool has_data = false;
decimal Result = 0;
- foreach (ValueTableRow row in _rows)
+ foreach (var row in _rows)
{
- IValue current_value = row.Get(Column);
+ var current_value = row.Get(Column);
if (current_value.SystemType == BasicTypes.Number)
{
has_data = true;
@@ -239,10 +239,7 @@ public IValue Total(IValue columnIndex)
}
}
- if (has_data)
- return ValueFactory.Create(Result);
-
- return ValueFactory.Create();
+ return has_data ? ValueFactory.Create(Result) : ValueFactory.Create();
}
///
@@ -255,12 +252,12 @@ public IValue Total(IValue columnIndex)
[ContextMethod("Найти", "Find")]
public IValue Find(IValue value, string columnNames = null)
{
- List processing_list = GetProcessingColumnList(columnNames);
+ var processing_list = GetProcessingColumnList(columnNames);
foreach (ValueTableRow row in _rows)
{
- foreach (ValueTableColumn col in processing_list)
+ foreach (var col in processing_list)
{
- IValue current = row.Get(col);
+ var current = row.Get(col);
if (value.Equals(current))
return row;
}
@@ -270,9 +267,9 @@ public IValue Find(IValue value, string columnNames = null)
private bool CheckFilterCriteria(ValueTableRow Row, StructureImpl Filter)
{
- foreach (KeyAndValueImpl kv in Filter)
+ foreach (var kv in Filter)
{
- ValueTableColumn Column = Columns.FindColumnByName(kv.Key.AsString());
+ var Column = Columns.FindColumnByName(kv.Key.AsString());
if (Column == null)
throw WrongColumnNameException(kv.Key.AsString());
@@ -294,15 +291,32 @@ public ArrayImpl FindRows(StructureImpl filter)
if (filter == null)
throw RuntimeException.InvalidArgumentType();
- ArrayImpl Result = new ArrayImpl();
+ var result = new ArrayImpl();
- foreach (ValueTableRow row in _rows)
+ var mapped = ColumnsMap(filter);
+ var suitableIndex = Indexes.FindSuitableIndex(mapped.Keys());
+ var dataToScan = suitableIndex != null ? suitableIndex.GetData(mapped) : _rows;
+
+ foreach (var element in dataToScan)
{
+ var row = (ValueTableRow)element;
if (CheckFilterCriteria(row, filter))
- Result.Add(row);
+ result.Add(row);
}
- return Result;
+ return result;
+ }
+
+ private MapImpl ColumnsMap(StructureImpl filter)
+ {
+ var result = new MapImpl();
+ foreach (var kv in filter)
+ {
+ var key = Columns.FindColumnByName(kv.Key.AsString());
+ result.Insert(key, kv.Value);
+ }
+
+ return result;
}
///
@@ -312,6 +326,7 @@ public ArrayImpl FindRows(StructureImpl filter)
public void Clear()
{
_rows.Clear();
+ Indexes.Clear();
}
///
@@ -336,62 +351,72 @@ public ValueTableRow Get(int index)
[ContextMethod("Свернуть", "GroupBy")]
public void GroupBy(string groupColumnNames, string aggregateColumnNames = null)
{
- List GroupColumns = GetProcessingColumnList(groupColumnNames, true);
- List AggregateColumns = GetProcessingColumnList(aggregateColumnNames, true);
+ var GroupColumns = GetProcessingColumnList(groupColumnNames, true);
+ var AggregateColumns = GetProcessingColumnList(aggregateColumnNames, true);
- foreach (ValueTableColumn group_column in GroupColumns )
- if ( AggregateColumns.Find(x => x.Name==group_column.Name)!=null )
- throw ColumnsMixedException(group_column.Name);
+ CheckMixedColumns(GroupColumns, AggregateColumns);
var uniqueRows = new Dictionary(new RowsByColumnsEqComparer(GroupColumns) );
int new_idx = 0;
- foreach (ValueTableRow row in _rows)
+ foreach (var row in _rows)
{
- if (uniqueRows.ContainsKey(row))
+ if (!uniqueRows.TryGetValue(row, out var destination))
{
- ValueTableRow old_row = uniqueRows[row];
-
- foreach (var Column in AggregateColumns)
- {
- IValue current = row.Get(Column);
- if (current.SystemType == BasicTypes.Number)
- {
- decimal sum = old_row.Get(Column).AsNumber() + current.AsNumber();
- old_row.Set(Column, ValueFactory.Create(sum));
- }
- }
+ destination = _rows[new_idx++];
+ CopyRowData(row, destination, GroupColumns);
+ CopyRowData(row, destination, AggregateColumns);
+ uniqueRows.Add(destination, destination);
}
else
{
- ValueTableRow new_row = _rows[new_idx++];
-
- foreach (var Column in GroupColumns)
- new_row.Set(Column, row.Get(Column));
-
- foreach (var Column in AggregateColumns)
- if (row.Get(Column).SystemType != BasicTypes.Number)
- new_row.Set(Column, ValueFactory.Create(0));
- else
- new_row.Set(Column, row.Get(Column));
-
- uniqueRows.Add(new_row, new_row);
+ AppendRowData(row, destination, AggregateColumns);
}
}
_rows.RemoveRange(new_idx, _rows.Count()-new_idx);
int i = 0;
- while (i < _columns.Count())
+ while (i < Columns.Count())
{
- ValueTableColumn Column = _columns.FindColumnByIndex(i);
- if (GroupColumns.IndexOf(Column) == -1 && AggregateColumns.IndexOf(Column) == -1)
- _columns.Delete(Column);
+ var column = Columns.FindColumnByIndex(i);
+ if (GroupColumns.IndexOf(column) == -1 && AggregateColumns.IndexOf(column) == -1)
+ Columns.Delete(column);
else
++i;
}
}
+ private void CheckMixedColumns(List groupColumns, List aggregateColumns)
+ {
+ foreach (var groupColumn in groupColumns )
+ if ( aggregateColumns.Find(x => x.Name==groupColumn.Name)!=null )
+ throw ColumnsMixedException(groupColumn.Name);
+ }
+
+ private void CopyRowData(ValueTableRow source, ValueTableRow dest, IEnumerable columns)
+ {
+ foreach (var column in columns)
+ dest.Set(column, source.Get(column));
+ }
+
+ private void AppendRowData(ValueTableRow source, ValueTableRow dest, IEnumerable columns)
+ {
+ foreach (var column in columns)
+ {
+ var value1 = GetNumeric(source, column);
+ var value2 = GetNumeric(dest, column);
+ dest.Set(column, ValueFactory.Add(value1, value2));
+ }
+ }
+
+ private IValue GetNumeric(ValueTableRow row, ValueTableColumn column)
+ {
+ var value = row.Get(column);
+ if (value.SystemType == BasicTypes.Number) return value;
+ return ValueFactory.Create(0);
+ }
+
private class RowsByColumnsEqComparer : IEqualityComparer
{
private List _columns;
@@ -426,9 +451,9 @@ private int IndexByValue(IValue item)
int index;
- if (item is ValueTableRow)
+ if (item is ValueTableRow row)
{
- index = IndexOf(item as ValueTableRow);
+ index = IndexOf(row);
if (index == -1)
throw new RuntimeException("Строка не принадлежит таблице значений");
}
@@ -490,11 +515,10 @@ public void Move(IValue row, int offset)
[ContextMethod("СкопироватьКолонки", "CopyColumns")]
public ValueTable CopyColumns(string columnNames = null)
{
- ValueTable Result = new ValueTable();
-
- List columns = GetProcessingColumnList(columnNames);
+ var Result = new ValueTable();
+ var columns = GetProcessingColumnList(columnNames);
- foreach (ValueTableColumn Column in columns)
+ foreach (var Column in columns)
{
Result.Columns.Add(Column.Name, Column.ValueType, Column.Title, Column.Width);
}
@@ -516,8 +540,8 @@ public ValueTable CopyColumns(string columnNames = null)
[ContextMethod("Скопировать", "Copy")]
public ValueTable Copy(IValue rows = null, string columnNames = null)
{
- ValueTable Result = CopyColumns(columnNames);
- List columns = GetProcessingColumnList(columnNames);
+ var Result = CopyColumns(columnNames);
+ var columns = GetProcessingColumnList(columnNames);
IEnumerable requestedRows;
if (rows == null)
@@ -544,8 +568,8 @@ public ValueTable Copy(IValue rows = null, string columnNames = null)
foreach (var row in requestedRows)
{
- ValueTableRow new_row = Result.Add();
- foreach (ValueTableColumn Column in columns)
+ var new_row = Result.Add();
+ foreach (var Column in columns)
{
new_row.Set(columnMap[Column], row.Get(Column));
}
@@ -672,6 +696,11 @@ public void ChooseRow(string title = null, IValue startRow = null)
throw new NotSupportedException();
}
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
public override IEnumerator GetEnumerator()
{
foreach (var item in _rows)
@@ -706,5 +735,17 @@ private static RuntimeException ColumnsMixedException(string columnName)
{
return new RuntimeException(string.Format("Колонка '{0}' не может одновременно быть колонкой группировки и колонкой суммирования", columnName));
}
+
+ public string GetName(IValue field)
+ {
+ if (field is ValueTableColumn column)
+ return column.Name;
+ throw RuntimeException.InvalidArgumentType(nameof(field));
+ }
+
+ public IValue GetField(string name)
+ {
+ return Columns.FindColumnByName(name);
+ }
}
}
diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs
index 5c9ce285c..3c562e0b9 100644
--- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs
+++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumn.cs
@@ -26,16 +26,18 @@ public class ValueTableColumn : AutoContext
private TypeDescription _valueType;
private int _width;
private readonly WeakReference _owner;
+ private readonly int _id;
private static TypeDescriptor _instanceType = typeof(ValueTableColumn).GetTypeFromClassMarkup();
- public ValueTableColumn(ValueTableColumnCollection owner, string name, string title, TypeDescription type, int width)
+ public ValueTableColumn(ValueTableColumnCollection owner, int id, string name, string title, TypeDescription type, int width)
: base(_instanceType)
{
_name = name;
_title = title;
_valueType = type ?? new TypeDescription();
_width = width;
+ _id = id;
_owner = new WeakReference(owner);
}
@@ -92,5 +94,10 @@ public int Width
get { return _width; }
set { _width = value; }
}
+
+ public override int GetHashCode()
+ {
+ return _id;
+ }
}
}
diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs
index 578e6b01a..2f4134b66 100644
--- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs
+++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableColumnCollection.cs
@@ -7,6 +7,7 @@ This Source Code Form is subject to the terms of the
using System;
using System.Collections.Generic;
+using System.Linq;
using OneScript.Commons;
using OneScript.Contexts;
using OneScript.Exceptions;
@@ -27,6 +28,7 @@ public class ValueTableColumnCollection : DynamicPropertiesAccessor, ICollection
private readonly List _columns = new List();
private readonly StringComparer _namesComparer = StringComparer.OrdinalIgnoreCase;
private readonly ValueTable _owner;
+ private int maxColumnId = 0;
private static readonly TypeDescriptor _objectType = typeof(ValueTableColumnCollection).GetTypeFromClassMarkup();
@@ -50,7 +52,7 @@ public ValueTableColumn Add(string name, TypeDescription type = null, string tit
if (FindColumnByName(name) != null)
throw new RuntimeException("Неверное имя колонки " + name);
- var column = new ValueTableColumn(this, name, title, type, width);
+ var column = new ValueTableColumn(this, ++maxColumnId, name, title, type, width);
_columns.Add(column);
return column;
@@ -71,7 +73,7 @@ public ValueTableColumn Insert(int index, string name, TypeDescription type = nu
if (FindColumnByName(name) != null)
throw new RuntimeException("Неверное имя колонки " + name);
- ValueTableColumn column = new ValueTableColumn(this, name, title, type, width);
+ ValueTableColumn column = new ValueTableColumn(this, ++maxColumnId, name, title, type, width);
_columns.Insert(index, column);
return column;
@@ -125,10 +127,26 @@ public void Delete(IValue column)
{
column = column.GetRawValue();
var vtColumn = GetColumnByIIndex(column);
- _owner.ForEach(x=>x.OnOwnerColumnRemoval(vtColumn));
+ _owner.ForEach((ValueTableRow x)=>
+ {
+ x.OnOwnerColumnRemoval(vtColumn);
+ });
+ _owner.Indexes.FieldRemoved(column);
_columns.Remove(vtColumn);
}
+ ///
+ /// Удаляет все колонки
+ ///
+ [ContextMethod("Очистить", "Clear")]
+ public void Clear()
+ {
+ while (_columns.Any())
+ {
+ Delete(_columns[0]);
+ }
+ }
+
public ValueTableColumn FindColumnByName(string name)
{
return _columns.Find(column => _namesComparer.Equals(name, column.Name));
diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableIndex.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableIndex.cs
deleted file mode 100644
index 75c4566ca..000000000
--- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableIndex.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-/*----------------------------------------------------------
-This Source Code Form is subject to the terms of the
-Mozilla Public License, v.2.0. If a copy of the MPL
-was not distributed with this file, You can obtain one
-at http://mozilla.org/MPL/2.0/.
-----------------------------------------------------------*/
-
-using OneScript.Contexts;
-using OneScript.Types;
-using ScriptEngine.Machine.Contexts;
-using ScriptEngine.Types;
-
-namespace OneScript.StandardLibrary.Collections.ValueTable
-{
- [ContextClass("ИндексКоллекции", "CollectionIndex", TypeUUID = "48D150D4-A0DA-47CA-AEA3-D4078A731C11")]
- public class CollectionIndex : ContextIValueImpl
- {
- private static readonly TypeDescriptor _objectType = typeof(ValueTableColumnCollection).GetTypeFromClassMarkup();
-
- public CollectionIndex() : base(_objectType)
- {
- }
-
- }
-}
diff --git a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableRow.cs b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableRow.cs
index 0ef5c7c06..df3f75fee 100644
--- a/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableRow.cs
+++ b/src/OneScript.StandardLibrary/Collections/ValueTable/ValueTableRow.cs
@@ -84,18 +84,20 @@ public IValue Get(ValueTableColumn c)
public void Set(int index, IValue value)
{
var C = Owner().Columns.FindColumnByIndex(index);
- _data[C] = C.ValueType.AdjustValue(value);
+ Set(C, value);
}
public void Set(IValue index, IValue value)
{
var C = Owner().Columns.GetColumnByIIndex(index);
- _data[C] = C.ValueType.AdjustValue(value);
+ Set(C, value);
}
public void Set(ValueTableColumn column, IValue value)
{
+ Owner().Indexes.ElementRemoved(this);
_data[column] = column.ValueType.AdjustValue(value);
+ Owner().Indexes.ElementAdded(this);
}
public void OnOwnerColumnRemoval(IValue column)
@@ -105,7 +107,7 @@ public void OnOwnerColumnRemoval(IValue column)
public IEnumerator GetEnumerator()
{
- foreach (ValueTableColumn item in Owner().Columns)
+ foreach (var item in Owner().Columns)
{
yield return TryValue(item);
}
@@ -143,14 +145,14 @@ public override bool IsPropWritable(int propNum)
public override IValue GetPropValue(int propNum)
{
- ValueTableColumn C = Owner().Columns.FindColumnByIndex(propNum);
+ var C = Owner().Columns.FindColumnByIndex(propNum);
return TryValue(C);
}
public override void SetPropValue(int propNum, IValue newVal)
{
- ValueTableColumn C = Owner().Columns.FindColumnByIndex(propNum);
- _data[C] = C.ValueType.AdjustValue(newVal);
+ var C = Owner().Columns.FindColumnByIndex(propNum);
+ Set(C, newVal);
}
private ValueTableColumn GetColumnByIIndex(IValue index)
diff --git a/src/OneScript.StandardLibrary/DelegateAction.cs b/src/OneScript.StandardLibrary/DelegateAction.cs
index 017b7844f..b668ee017 100644
--- a/src/OneScript.StandardLibrary/DelegateAction.cs
+++ b/src/OneScript.StandardLibrary/DelegateAction.cs
@@ -30,6 +30,7 @@ static DelegateAction()
{
var builder = BslMethodBuilder.Create()
.DeclaringType(typeof(DelegateAction))
+ .ReturnType(typeof(BslValue))
.SetNames(MethodName_Ru, MethodName_En);
ExecuteMethodInfo = builder.Build();
@@ -66,10 +67,7 @@ public override int GetMethodsCount()
public override BslMethodInfo GetMethodInfo(int methodNumber)
{
- return BslMethodBuilder.Create()
- .SetNames(MethodName_Ru, MethodName_En)
- .ReturnType(typeof(BslValue))
- .Build();
+ return ExecuteMethodInfo;
}
public override void CallAsFunction(int methodNumber, IValue[] arguments, out IValue retValue)
diff --git a/src/OneScript.StandardLibrary/Json/JSONWriterSettings.cs b/src/OneScript.StandardLibrary/Json/JSONWriterSettings.cs
index d6e9df75b..bbd82ebd6 100644
--- a/src/OneScript.StandardLibrary/Json/JSONWriterSettings.cs
+++ b/src/OneScript.StandardLibrary/Json/JSONWriterSettings.cs
@@ -86,7 +86,7 @@ public JSONWriterSettings(JSONLineBreakEnum NewLines = JSONLineBreakEnum.Auto, s
/// Определяет, будет ли экранироваться слеш (косая черта) при записи значения.
/// Значение по умолчанию: Ложь.
[ScriptConstructor(Name = "По описанию параметров записи")]
- public static JSONWriterSettings Constructor(IValue newLines = null, IValue paddingSymbols = null, IValue useDoubleQuotes = null, IValue escapeCharacters = null, IValue escapeAngleBrackets = null, IValue escapeLineTerminators = null, IValue escapeAmpersand = null, IValue escapeSingleQuotes = null, IValue escapeSlash = null)
+ public static JSONWriterSettings ParametrizedConstructor(IValue newLines = null, IValue paddingSymbols = null, IValue useDoubleQuotes = null, IValue escapeCharacters = null, IValue escapeAngleBrackets = null, IValue escapeLineTerminators = null, IValue escapeAmpersand = null, IValue escapeSingleQuotes = null, IValue escapeSlash = null)
{
return new JSONWriterSettings((newLines as ClrEnumValueWrapper)?.UnderlyingValue ?? JSONLineBreakEnum.None,
paddingSymbols?.AsString(),
diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs
index 217932042..a42f26ce6 100644
--- a/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs
+++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiComponent.cs
@@ -17,9 +17,9 @@ namespace OneScript.StandardLibrary.NativeApi
///
/// Экземпляр внешней компоненты Native API
///
- class NativeApiComponent : NativeApiValue, IRuntimeContextInstance, IValue
+ class NativeApiComponent : NativeApiValue, IRuntimeContextInstance, IDisposable
{
- private readonly IntPtr _object;
+ private IntPtr _object;
public override IRuntimeContextInstance AsObject()
{
@@ -96,11 +96,6 @@ public NativeApiComponent(object host, NativeApiLibrary library, TypeDescriptor
DefineType(typeDef);
}
- public void Dispose()
- {
- try { NativeApiProxy.DestroyObject(_object); } catch (Exception) { }
- }
-
public bool IsIndexed => true;
public bool DynamicMethodSignatures => false;
@@ -271,5 +266,36 @@ public void CallAsFunction(int methodNumber, IValue[] arguments, out IValue retV
}
retValue = result;
}
+
+ private void ReleaseUnmanagedResources(bool isDisposing)
+ {
+ if (_object == IntPtr.Zero)
+ return;
+
+ try
+ {
+ NativeApiProxy.DestroyObject(_object);
+ }
+ catch (Exception)
+ {
+ if (isDisposing)
+ throw;
+ }
+ finally
+ {
+ _object = IntPtr.Zero;
+ }
+ }
+
+ public void Dispose()
+ {
+ ReleaseUnmanagedResources(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ~NativeApiComponent()
+ {
+ ReleaseUnmanagedResources(false);
+ }
}
}
diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiKernel.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiKernel.cs
index 1508a5372..ad9020707 100644
--- a/src/OneScript.StandardLibrary/NativeApi/NativeApiKernel.cs
+++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiKernel.cs
@@ -22,7 +22,7 @@ public static bool IsLinux
}
private const String KernelWin = "kernel32.dll";
- private const String KernelLin = "libdl.so";
+ private const String KernelLin = "libdl.so.2";
public static IntPtr LoadLibrary(string filename)
{
diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs
index 43462570e..3746d382c 100644
--- a/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs
+++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiLibrary.cs
@@ -19,7 +19,7 @@ namespace OneScript.StandardLibrary.NativeApi
/// Класс, ассоциированный с экземпляром библиотеки внешних компонент
/// Native API и осуществляющий непосредственное создание экземпляра компоненты.
///
- class NativeApiLibrary
+ class NativeApiLibrary : IDisposable
{
private delegate IntPtr GetClassNames();
@@ -47,15 +47,6 @@ public NativeApiLibrary(string filepath, string identifier, ITypeManager typeMan
RegisterComponents(identifier, typeManager);
}
- public void Dispose()
- {
- foreach (var component in _components)
- component.Dispose();
- if (Loaded && NativeApiKernel.FreeLibrary(Module))
- if (!String.IsNullOrEmpty(_tempfile))
- try { File.Delete(_tempfile); } catch (Exception) { }
- }
-
public IntPtr Module { get; private set; } = IntPtr.Zero;
public Boolean Loaded
@@ -84,5 +75,40 @@ public IValue CreateComponent(ITypeManager typeManager, object host, String type
_components.Add(component);
return component;
}
+
+ private void ReleaseUnmanagedResources(bool isDisposing)
+ {
+ try
+ {
+ foreach (var component in _components)
+ {
+ component.Dispose();
+ }
+
+ if (Loaded && NativeApiKernel.FreeLibrary(Module))
+ {
+ if (!String.IsNullOrEmpty(_tempfile))
+ {
+ File.Delete(_tempfile);
+ }
+ }
+ }
+ catch (Exception)
+ {
+ if (isDisposing)
+ throw;
+ }
+ }
+
+ public void Dispose()
+ {
+ ReleaseUnmanagedResources(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ~NativeApiLibrary()
+ {
+ ReleaseUnmanagedResources(false);
+ }
}
}
diff --git a/src/OneScript.StandardLibrary/NativeApi/NativeApiProxy.cs b/src/OneScript.StandardLibrary/NativeApi/NativeApiProxy.cs
index 6e20bad0b..ab7cc697b 100644
--- a/src/OneScript.StandardLibrary/NativeApi/NativeApiProxy.cs
+++ b/src/OneScript.StandardLibrary/NativeApi/NativeApiProxy.cs
@@ -106,33 +106,33 @@ public delegate void TGetVariant(IntPtr ptr, Int32 num
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
public delegate bool TCallAsFunc(IntPtr ptr, Int32 lMethodNum, IntPtr value, PointerDelegate response);
- public static TGetClassObject GetClassObject;
- public static TDestroyObject DestroyObject;
- public static TCreateVariant CreateVariant;
- public static TFreeVariant FreeVariant;
- public static TGetNProps GetNProps;
- public static TFindProp FindProp;
- public static TIsPropReadable IsPropReadable;
- public static TIsPropWritable IsPropWritable;
- public static TGetPropName GetPropName;
- public static TGetPropVal GetPropVal;
- public static TSetPropVal SetPropVal;
- public static TGetVariant GetVariant;
- public static TSetVariantEmpty SetVariantEmpty;
- public static TSetVariantBool SetVariantBool;
- public static TSetVariantReal SetVariantReal;
- public static TSetVariantBlob SetVariantBlob;
- public static TSetVariantInt SetVariantInt;
- public static TSetVariantStr SetVariantStr;
- public static TGetNMethods GetNMethods;
- public static TFindMethod FindMethod;
- public static TGetMethodName GetMethodName;
- public static TGetNParams GetNParams;
- public static THasParamDefValue HasParamDefValue;
- public static TGetParamDefValue GetParamDefValue;
- public static THasRetVal HasRetVal;
- public static TCallAsProc CallAsProc;
- public static TCallAsFunc CallAsFunc;
+ public static readonly TGetClassObject GetClassObject;
+ public static readonly TDestroyObject DestroyObject;
+ public static readonly TCreateVariant CreateVariant;
+ public static readonly TFreeVariant FreeVariant;
+ public static readonly TGetNProps GetNProps;
+ public static readonly TFindProp FindProp;
+ public static readonly TIsPropReadable IsPropReadable;
+ public static readonly TIsPropWritable IsPropWritable;
+ public static readonly TGetPropName GetPropName;
+ public static readonly TGetPropVal GetPropVal;
+ public static readonly TSetPropVal SetPropVal;
+ public static readonly TGetVariant GetVariant;
+ public static readonly TSetVariantEmpty SetVariantEmpty;
+ public static readonly TSetVariantBool SetVariantBool;
+ public static readonly TSetVariantReal SetVariantReal;
+ public static readonly TSetVariantBlob SetVariantBlob;
+ public static readonly TSetVariantInt SetVariantInt;
+ public static readonly TSetVariantStr SetVariantStr;
+ public static readonly TGetNMethods GetNMethods;
+ public static readonly TFindMethod FindMethod;
+ public static readonly TGetMethodName GetMethodName;
+ public static readonly TGetNParams GetNParams;
+ public static readonly THasParamDefValue HasParamDefValue;
+ public static readonly TGetParamDefValue GetParamDefValue;
+ public static readonly THasRetVal HasRetVal;
+ public static readonly TCallAsProc CallAsProc;
+ public static readonly TCallAsFunc CallAsFunc;
public static bool IsAvailable { get; private set; }
diff --git a/src/OneScript.StandardLibrary/Net/TCPClient.cs b/src/OneScript.StandardLibrary/Net/TCPClient.cs
index 346ae447f..44abe36a7 100644
--- a/src/OneScript.StandardLibrary/Net/TCPClient.cs
+++ b/src/OneScript.StandardLibrary/Net/TCPClient.cs
@@ -163,6 +163,16 @@ public int ReadTimeout
set { _client.GetStream().ReadTimeout = value; }
}
+ ///
+ /// Флаг ожидания наполнения буфера при приеме/отправке данных. По умолчанию - Ложь
+ ///
+ [ContextProperty("НеОткладывать", "NoDelay")]
+ public bool NoDelay
+ {
+ get { return _client.NoDelay; }
+ set { _client.NoDelay = value; }
+ }
+
private static Encoding GetEncodingByName(string encoding)
{
Encoding enc;
diff --git a/src/OneScript.StandardLibrary/Processes/ArgumentsParser.cs b/src/OneScript.StandardLibrary/Processes/ArgumentsParser.cs
index 88e22b283..6000d85ab 100644
--- a/src/OneScript.StandardLibrary/Processes/ArgumentsParser.cs
+++ b/src/OneScript.StandardLibrary/Processes/ArgumentsParser.cs
@@ -1,4 +1,4 @@
-/*----------------------------------------------------------
+/*----------------------------------------------------------
This Source Code Form is subject to the terms of the
Mozilla Public License, v.2.0. If a copy of the MPL
was not distributed with this file, You can obtain one
diff --git a/src/OneScript.StandardLibrary/Processes/ProcessContext.cs b/src/OneScript.StandardLibrary/Processes/ProcessContext.cs
index a0ae09708..71fea5b45 100644
--- a/src/OneScript.StandardLibrary/Processes/ProcessContext.cs
+++ b/src/OneScript.StandardLibrary/Processes/ProcessContext.cs
@@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the
using System;
using System.Diagnostics;
using System.Linq;
+using System.Runtime.InteropServices;
using OneScript.Contexts;
using OneScript.Exceptions;
using OneScript.StandardLibrary.Collections;
@@ -274,14 +275,24 @@ public static ProcessStartInfo PrepareProcessStartupInfo(string cmdLine, string
sInfo.FileName = ExtractExecutableName(cmdLine, out argsPosition);
if (currentDir != null)
sInfo.WorkingDirectory = currentDir;
-
- var arguments = argsPosition >= cmdLine.Length
- ? Array.Empty()
- : new ArgumentsParser(cmdLine[argsPosition..]).GetArguments();
- foreach (var argument in arguments)
+ // Поведение под MacOS и остальные системы различается
+ // Страдает обратная совместимость и неясны до конца синтаксисы.
+ // См. https://github.com/EvilBeaver/OneScript/issues/1299
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ sInfo.Arguments = argsPosition >= cmdLine.Length ? "" : cmdLine.Substring(argsPosition);
+ }
+ else
{
- sInfo.ArgumentList.Add(argument);
+ var arguments = argsPosition >= cmdLine.Length
+ ? Array.Empty()
+ : new ArgumentsParser(cmdLine[argsPosition..]).GetArguments();
+
+ foreach (var argument in arguments)
+ {
+ sInfo.ArgumentList.Add(argument);
+ }
}
return sInfo;
diff --git a/src/OneScript.StandardLibrary/Processes/ProcessOutputWrapper.cs b/src/OneScript.StandardLibrary/Processes/ProcessOutputWrapper.cs
index 6cd35a45b..db67e18be 100644
--- a/src/OneScript.StandardLibrary/Processes/ProcessOutputWrapper.cs
+++ b/src/OneScript.StandardLibrary/Processes/ProcessOutputWrapper.cs
@@ -15,11 +15,10 @@ namespace OneScript.StandardLibrary.Processes
{
class ProcessOutputWrapper : TextReader
{
- private sys.Process _process;
- private OutputVariant _variant;
- private StringBuilder _buffer = new StringBuilder(4096);
- private ReaderWriterLockSlim _locker;
-
+ private readonly sys.Process _process;
+ private readonly OutputVariant _variant;
+ private readonly StringBuilder _buffer = new StringBuilder(4096);
+
private int _bufferIndex = 0;
private bool AlreadyReading { get; set; }
@@ -36,7 +35,6 @@ public ProcessOutputWrapper(sys.Process process, OutputVariant variant)
{
_process = process;
_variant = variant;
- _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
}
public void StartReading()
diff --git a/src/OneScript.StandardLibrary/Reflector.cs b/src/OneScript.StandardLibrary/Reflector.cs
index fdb6e3ac3..0032434d6 100644
--- a/src/OneScript.StandardLibrary/Reflector.cs
+++ b/src/OneScript.StandardLibrary/Reflector.cs
@@ -9,6 +9,7 @@ This Source Code Form is subject to the terms of the
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
+using OneScript.Commons;
using OneScript.Contexts;
using OneScript.Exceptions;
using OneScript.Execution;
@@ -30,6 +31,13 @@ namespace OneScript.StandardLibrary
[ContextClass("Рефлектор","Reflector")]
public class ReflectorContext : AutoContext
{
+ private readonly ITypeManager _typeManager;
+
+ private ReflectorContext(ITypeManager typeManager)
+ {
+ _typeManager = typeManager;
+ }
+
///
/// Вызывает метод по его имени.
///
@@ -43,8 +51,12 @@ public IValue CallMethod(IRuntimeContextInstance target, string methodName, Arra
var methodIdx = target.GetMethodNumber(methodName);
var methInfo = target.GetMethodInfo(methodIdx);
- var argsToPass = GetArgsToPass(arguments, methInfo.GetParameters());
-
+ IValue[] argsToPass;
+ if (target.DynamicMethodSignatures)
+ argsToPass = arguments?.ToArray() ?? Array.Empty();
+ else
+ argsToPass = GetArgsToPass(arguments, methInfo.GetParameters());
+
IValue retValue = ValueFactory.Create();
if (methInfo.IsFunction())
{
@@ -71,34 +83,39 @@ public IValue CallMethod(IRuntimeContextInstance target, string methodName, Arra
private static IValue[] GetArgsToPass(ArrayImpl arguments, ParameterInfo[] parameters)
{
- var argsToPass = new List();
- if (arguments != null)
- {
- argsToPass.AddRange(arguments);
- }
-
- if (parameters.Length < argsToPass.Count)
+ var argValues = arguments?.ToArray() ?? Array.Empty();
+ // ArrayImpl не может (не должен!) содержать null или NotAValidValue
+
+ if (argValues.Length > parameters.Length)
throw RuntimeException.TooManyArgumentsPassed();
- for (int i = 0; i < argsToPass.Count; i++)
+ var argsToPass = new IValue[parameters.Length];
+
+ int i = 0;
+ for (; i < argValues.Length; i++)
{
if (parameters[i].IsByRef())
- argsToPass[i] = Variable.Create(argsToPass[i], $"reflectorArg{i}");
+ argsToPass[i] = Variable.Create(argValues[i], "");
+ else
+ argsToPass[i] = argValues[i];
}
- while (argsToPass.Count < parameters.Length)
+ for (; i < parameters.Length; i++)
{
- argsToPass.Add(null);
+ if (!parameters[i].HasDefaultValue)
+ throw RuntimeException.TooFewArgumentsPassed();
+
+ // else keep null as a default value
}
- return argsToPass.ToArray();
+ return argsToPass;
}
///
- /// Проверяет существование указанного метода у переданного объекта..
+ /// Проверяет существование указанного метода у переданного объекта.
///
/// Объект, из которого получаем таблицу методов.
/// Имя метода для вызова
- /// Истину, если метод существует, и Ложь в обратном случае.
+ /// Истина, если метод существует, и Ложь в обратном случае.
[ContextMethod("МетодСуществует", "MethodExists")]
public bool MethodExists(IValue target, string methodName)
{
@@ -198,10 +215,10 @@ private static RuntimeException NonReflectableType()
}
///
- /// Получает таблицу методов для переданного объекта..
+ /// Получает таблицу методов для переданного объекта.
///
/// Объект, из которого получаем таблицу методов.
- /// Таблица значений колонками: Имя, Количество, ЭтоФункция, Аннотации
+ /// Таблица значений с колонками: Имя, Количество, ЭтоФункция, Аннотации, Параметры, Экспорт
[ContextMethod("ПолучитьТаблицуМетодов", "GetMethodsTable")]
public ValueTable GetMethodsTable(IValue target)
{
@@ -312,7 +329,7 @@ private static void FillMethodsTable(ValueTable result, IEnumerable
- /// Получает таблицу свойств для переданного объекта..
+ /// Получает таблицу свойств для переданного объекта.
///
/// Объект, из которого получаем таблицу свойств.
/// Включить в результат приватные поля
- /// Таблица значений с колонками - Имя, Аннотации
+ /// Таблица значений с колонками - Имя, Аннотации, Экспорт
[ContextMethod("ПолучитьТаблицуСвойств", "GetPropertiesTable")]
public ValueTable GetPropertiesTable(IValue target, bool withPrivate = false)
{
@@ -478,10 +495,54 @@ public static Type ReflectContext(Type clrType)
.Build();
}
+ ///
+ /// Возвращает все известные типы
+ ///
+ /// Структура - Условия поиска. Ключ - имя колонки, значение - искомое значение
+ ///
+ /// ТаблицаЗначений:
+ /// * Имя - Строка - Имя типа
+ /// * Значение - Тип - Тип
+ /// * Примитивный - Булево - Это примитивный тип
+ /// * Пользовательский - Булево - Это пользовательский типа
+ /// * Коллекция - Булево - Это коллекция
+ ///
+ [ContextMethod("ИзвестныеТипы", "KnownTypes")]
+ public ValueTable KnownTypes(StructureImpl filter = default)
+ {
+ var result = new ValueTable();
+
+ var nameColumn = result.Columns.Add("Имя", TypeDescription.StringType());
+ var valueColumn = result.Columns.Add("Значение", new TypeDescription(new List() { new BslTypeValue(BasicTypes.Type) }));
+ var primitiveColumn = result.Columns.Add("Примитивный", TypeDescription.BooleanType());
+ var userColumn = result.Columns.Add("Пользовательский", TypeDescription.BooleanType());
+ var collectionColumn = result.Columns.Add("Коллекция", TypeDescription.BooleanType());
+
+ _typeManager.RegisteredTypes().ForEach(descriptor =>
+ {
+ var row = result.Add();
+
+ row.Set(nameColumn, ValueFactory.Create(descriptor.ToString()));
+ row.Set(valueColumn, new BslTypeValue(descriptor));
+ row.Set(primitiveColumn, ValueFactory.Create(descriptor.ImplementingClass.IsSubclassOf(typeof(BslPrimitiveValue))));
+ row.Set(userColumn, ValueFactory.Create(descriptor.ImplementingClass == typeof(AttachedScriptsFactory)));
+ row.Set(collectionColumn, ValueFactory.Create(
+ descriptor.ImplementingClass.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICollectionContext<>))
+ ));
+ });
+
+ if (filter != default)
+ {
+ result = result.Copy(filter);
+ }
+
+ return result;
+ }
+
[ScriptConstructor]
- public static IRuntimeContextInstance CreateNew()
+ public static ReflectorContext CreateNew(TypeActivationContext context)
{
- return new ReflectorContext();
+ return new ReflectorContext(context.TypeManager);
}
}
}
diff --git a/src/OneScript.StandardLibrary/Text/TextReadImpl.cs b/src/OneScript.StandardLibrary/Text/TextReadImpl.cs
index b66f5c5af..7083150a5 100644
--- a/src/OneScript.StandardLibrary/Text/TextReadImpl.cs
+++ b/src/OneScript.StandardLibrary/Text/TextReadImpl.cs
@@ -179,7 +179,7 @@ public static TextReadImpl Constructor (IValue input)
/// Открывать файл монопольно
/// ЧтениеТекста
[ScriptConstructor(Name = "На основании потока или файла")]
- public static TextReadImpl Constructor(IValue input, IValue encoding = null,
+ public static TextReadImpl ConstructorWithEncoding(IValue input, IValue encoding = null,
IValue lineDelimiter = null, IValue eolDelimiter = null, IValue monopoly = null)
{
var reader = new TextReadImpl();
diff --git a/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs b/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs
index 9655f91ac..d09602c57 100644
--- a/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs
+++ b/src/OneScript.StandardLibrary/XDTO/XDTOSerializer.cs
@@ -22,14 +22,12 @@ namespace OneScript.StandardLibrary.XDTO
[ContextClass("СериализаторXDTO", "XDTOSerializer")]
public sealed class XDTOSerializer : AutoContext
{
- private readonly ITypeManager _typeManager;
private readonly XmlGlobalFunctions _xmlGlobalFunctions;
private readonly XmlNodeTypeEnum _xmlNodeEnum;
- private XDTOSerializer(ITypeManager typeManager, IGlobalsManager globalsManager)
+ private XDTOSerializer(IGlobalsManager globalsManager)
{
- _typeManager = typeManager;
_xmlGlobalFunctions = globalsManager.GetInstance();
_xmlNodeEnum = globalsManager.GetInstance();
}
@@ -263,7 +261,7 @@ public IValue ReadXML(XmlReaderImpl xmlReader, IValue valueType = null)
public static XDTOSerializer CreateInstance(TypeActivationContext context)
{
var globalsManager = context.Services.Resolve();
- return new XDTOSerializer(context.TypeManager, globalsManager);
+ return new XDTOSerializer(globalsManager);
}
#endregion
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs
index a1b64664e..98b5e8b29 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSAppInfo.cs
@@ -60,7 +60,7 @@ public string Source
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs
index 616f09d09..a64033baa 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSComplexTypeDefinition.cs
@@ -445,7 +445,7 @@ public IXSComponent Content
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs
index efbcebb8a..198dfe43f 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSDocumentation.cs
@@ -67,7 +67,7 @@ public string Language
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs
index 3a299bd23..7f9ce9831 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSEnumerationFacet.cs
@@ -106,7 +106,7 @@ public IValue Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs
index 5a7217d0b..9f806fca7 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSFractionDigitsFacet.cs
@@ -96,7 +96,7 @@ public decimal Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs
index b759a6059..7deead4ed 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSInclude.cs
@@ -75,7 +75,7 @@ public string SchemaLocation
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs
index 58d9751de..c1c727bec 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSLengthFacet.cs
@@ -96,7 +96,7 @@ public decimal Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs
index 0d89d09b3..fe2549c67 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxExclusiveFacet.cs
@@ -112,7 +112,7 @@ public IValue Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs
index d1aab68db..a20c209c0 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxInclusiveFacet.cs
@@ -113,7 +113,7 @@ public IValue Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs
index 397c0344d..4a5a5764f 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMaxLengthFacet.cs
@@ -96,7 +96,7 @@ public decimal Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs
index 98a5d88b1..881b61d2a 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinExclusiveFacet.cs
@@ -112,7 +112,7 @@ public IValue Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs
index d4c83e859..4108af205 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinInclusiveFacet.cs
@@ -112,7 +112,7 @@ public IValue Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs
index 322763457..282b1422e 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSMinLengthFacet.cs
@@ -96,7 +96,7 @@ public decimal Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs
index c12979632..f9c99c43c 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSModelGroupDefinition.cs
@@ -162,7 +162,7 @@ public XMLExpandedName Reference
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs
index 53792aa9c..56a81e02e 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSPatternFacet.cs
@@ -95,7 +95,7 @@ public string Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs
index bbafd61c4..fa039c378 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSSimpleTypeDefinition.cs
@@ -264,7 +264,7 @@ public XMLExpandedName ItemTypeName
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs
index 498bae27d..dbb3190f6 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSTotalDigitsFacet.cs
@@ -96,7 +96,7 @@ public decimal Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs
index a71ce3216..02870bbb6 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWhitespaceFacet.cs
@@ -131,7 +131,7 @@ public XSWhitespaceHandling Value
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs
index f5718511d..33ffd8740 100644
--- a/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs
+++ b/src/OneScript.StandardLibrary/XMLSchema/Objects/XSWildcard.cs
@@ -165,7 +165,7 @@ public string LexicalNamespaceConstraint
#region Methods
[ContextMethod("КлонироватьКомпоненту", "CloneComponent")]
- public IXSComponent CloneComponent(bool recursive) => throw new NotImplementedException();
+ public IXSComponent CloneComponent(bool recursive = true) => throw new NotImplementedException();
[ContextMethod("ОбновитьЭлементDOM", "UpdateDOMElement")]
public void UpdateDOMElement() => throw new NotImplementedException();
diff --git a/src/OneScriptDocumenter/OneScriptDocumenter.csproj b/src/OneScriptDocumenter/OneScriptDocumenter.csproj
index 225f8a3bd..b97bdd1cb 100644
--- a/src/OneScriptDocumenter/OneScriptDocumenter.csproj
+++ b/src/OneScriptDocumenter/OneScriptDocumenter.csproj
@@ -3,7 +3,7 @@
- netcoreapp3.1
+ net6.0
Exe
OneScript Libraries Documenter
diff --git a/src/ScriptEngine/Compiler/CompilerFrontend.cs b/src/ScriptEngine/Compiler/CompilerFrontend.cs
index 1c6fe1db8..3f1a9d965 100644
--- a/src/ScriptEngine/Compiler/CompilerFrontend.cs
+++ b/src/ScriptEngine/Compiler/CompilerFrontend.cs
@@ -5,13 +5,18 @@ This Source Code Form is subject to the terms of the
at http://mozilla.org/MPL/2.0/.
----------------------------------------------------------*/
using System;
+using System.Collections.Generic;
+using System.Linq;
+using OneScript.Commons;
using OneScript.Compilation;
using OneScript.Compilation.Binding;
+using OneScript.Contexts;
using OneScript.DependencyInjection;
using OneScript.Execution;
using OneScript.Language;
using OneScript.Language.SyntaxAnalysis;
using OneScript.Language.SyntaxAnalysis.AstNodes;
+using ScriptEngine.Machine;
using ScriptEngine.Machine.Contexts;
namespace ScriptEngine.Compiler
@@ -19,15 +24,20 @@ namespace ScriptEngine.Compiler
public class CompilerFrontend : CompilerFrontendBase
{
private readonly IDependencyResolver _dependencyResolver;
+ private readonly PredefinedInterfaceResolver _interfaceResolver;
private readonly CompilerBackendSelector _backendSelector;
public CompilerFrontend(
PreprocessorHandlers handlers,
IErrorSink errorSink,
IServiceContainer services,
- IDependencyResolver dependencyResolver) : base(handlers, errorSink, services)
+ IDependencyResolver dependencyResolver,
+ PredefinedInterfaceResolver interfaceResolver,
+ IEnumerable checkers) : base(handlers, errorSink, services)
{
_dependencyResolver = dependencyResolver;
+ _interfaceResolver = interfaceResolver;
+
_backendSelector = services.Resolve();
_backendSelector.NativeBackendInitializer = NativeInitializer;
@@ -61,7 +71,12 @@ protected override IExecutableModule CompileInternal(SymbolTable symbols, Module
{
var backend = _backendSelector.Select(parsedModule);
backend.Symbols = symbols;
- return backend.Compile(parsedModule, classType);
+
+ var module = backend.Compile(parsedModule, classType);
+
+ _interfaceResolver.Resolve(module);
+
+ return module;
}
protected override IExecutableModule CompileExpressionInternal(SymbolTable symbols, ModuleNode parsedModule)
diff --git a/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs b/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs
index c37e0938b..e361f4e9f 100644
--- a/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs
+++ b/src/ScriptEngine/Compiler/StackMachineCodeGenerator.cs
@@ -224,9 +224,23 @@ private static string[] GetVariableNames(SymbolScope localCtx)
return localCtx.Variables.Select(v => v.Name).ToArray();
}
+
+ protected override void VisitGotoNode(NonTerminalNode node)
+ {
+ throw new NotSupportedException();
+ }
+
+ protected override void VisitLabelNode(LabelNode node)
+ {
+ throw new NotSupportedException();
+ }
protected override void VisitMethod(MethodNode methodNode)
{
+ if (methodNode.IsAsync)
+ {
+ AddError(LocalizedErrors.AsyncMethodsNotSupported(), methodNode.Location);
+ }
var signature = methodNode.Signature;
var methodBuilder = NewMethod();
diff --git a/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs b/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs
index ccb3981a8..39b273efd 100644
--- a/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs
+++ b/src/ScriptEngine/Hosting/EngineBuilderExtensions.cs
@@ -15,6 +15,8 @@ This Source Code Form is subject to the terms of the
using OneScript.Language.SyntaxAnalysis;
using OneScript.Types;
using ScriptEngine.Machine;
+using ScriptEngine.Machine.Contexts;
+using ScriptEngine.Machine.Interfaces;
namespace ScriptEngine.Hosting
{
@@ -59,7 +61,7 @@ public static IEngineBuilder SetDefaultOptions(this IEngineBuilder builder)
services.RegisterEnumerable();
services.Register();
-
+ services.EnablePredefinedIterables();
services.Register(sp =>
{
var providers = sp.ResolveEnumerable();
diff --git a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs
index 8412de908..5b2335cc2 100755
--- a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs
+++ b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs
@@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the
----------------------------------------------------------*/
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using OneScript.Sources;
using System.Security.Cryptography;
@@ -16,6 +17,7 @@ This Source Code Form is subject to the terms of the
using OneScript.Exceptions;
using OneScript.Execution;
using OneScript.Types;
+using ScriptEngine.Machine.Interfaces;
namespace ScriptEngine.Machine.Contexts
{
@@ -212,9 +214,17 @@ public static UserScriptContextInstance ScriptFactory(TypeActivationContext cont
{
var module = _instance._loadedModules[context.TypeName];
- var type = context.TypeManager.GetTypeByName(context.TypeName);
-
- var newObj = new UserScriptContextInstance(module, type, arguments);
+ var type = context.TypeManager.GetTypeByName(context.TypeName);
+ UserScriptContextInstance newObj;
+ if (module.GetInterface() != null)
+ {
+ newObj = new UserIterableContextInstance(module, type, arguments);
+ }
+ else
+ {
+ newObj = new UserScriptContextInstance(module, type, arguments);
+ }
+
newObj.InitOwnData();
newObj.Initialize();
diff --git a/src/ScriptEngine/Machine/Contexts/BslPredefinedAnnotation.cs b/src/ScriptEngine/Machine/Contexts/BslPredefinedAnnotation.cs
new file mode 100644
index 000000000..cc14e4dbf
--- /dev/null
+++ b/src/ScriptEngine/Machine/Contexts/BslPredefinedAnnotation.cs
@@ -0,0 +1,21 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using OneScript.Contexts;
+using OneScript.Localization;
+
+namespace ScriptEngine.Machine.Contexts
+{
+ public static class BslPredefinedAnnotation
+ {
+ public static bool NameMatches(this BslAnnotationAttribute attribute, BilingualString names)
+ {
+ return names.HasName(attribute.Name, StringComparison.CurrentCultureIgnoreCase);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs
index 80f620dda..523896b67 100644
--- a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs
+++ b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs
@@ -127,7 +127,7 @@ private static bool TypeIsRuntimeCallableWrapper(Type type)
protected static (object[] values, ParameterModifier[] flags) MarshalArguments(IValue[] arguments)
{
var values = new object[arguments.Length];
- ParameterModifier[] flagsArray = null;
+ ParameterModifier[] flagsArray = new ParameterModifier[1];
if (arguments.Length > 0)
{
var flags = new ParameterModifier(arguments.Length);
@@ -137,7 +137,11 @@ protected static (object[] values, ParameterModifier[] flags) MarshalArguments(I
flags[i] = arguments[i] is IVariable;
}
- flagsArray = new[] { flags };
+ flagsArray[0] = flags;
+ }
+ else
+ {
+ flagsArray[0] = new ParameterModifier();
}
return (values, flagsArray);
@@ -312,7 +316,6 @@ protected virtual void Dispose(bool manualDispose)
{
GC.SuppressFinalize(this);
}
-
}
public void Dispose()
@@ -327,14 +330,8 @@ public void Dispose()
#endregion
- public override bool DynamicMethodSignatures
- {
- get
- {
- return true;
- }
- }
-
+ public override bool DynamicMethodSignatures => true;
+
[ScriptConstructor]
public static COMWrapperContext Constructor(IValue[] args)
{
diff --git a/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs b/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs
index ce73700d3..869d6d408 100644
--- a/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs
+++ b/src/ScriptEngine/Machine/Contexts/ExceptionInfoContext.cs
@@ -207,7 +207,7 @@ public static ExceptionInfoContext EmptyExceptionInfo()
private class EmptyScriptException : ScriptException
{
- public static EmptyScriptException Instance = new EmptyScriptException();
+ public static readonly EmptyScriptException Instance = new EmptyScriptException();
private EmptyScriptException() : base("")
{
LineNumber = 0;
diff --git a/src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs b/src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs
new file mode 100644
index 000000000..cf2b68783
--- /dev/null
+++ b/src/ScriptEngine/Machine/Contexts/ScriptedEnumeratorWrapper.cs
@@ -0,0 +1,82 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using OneScript.Contexts;
+using OneScript.Exceptions;
+using OneScript.Execution;
+using OneScript.Localization;
+using OneScript.Values;
+using ScriptEngine.Machine.Interfaces;
+
+namespace ScriptEngine.Machine.Contexts
+{
+ public sealed class ScriptedEnumeratorWrapper : IEnumerator
+ {
+ private readonly UserScriptContextInstance _userObject;
+
+ private BslScriptMethodInfo _moveNextMethod;
+ private BslScriptMethodInfo _getCurrentMethod;
+ private BslScriptMethodInfo _onDisposeMethod;
+
+ public ScriptedEnumeratorWrapper(UserScriptContextInstance userObject)
+ {
+ _userObject = userObject;
+ CheckAndSetMethods();
+ }
+
+ private void CheckAndSetMethods()
+ {
+ var bslInterface = _userObject.Module.GetInterface()
+ ?? IteratorBslInterfaceChecker.CheckModule(_userObject.Module);
+
+ _moveNextMethod = bslInterface.MoveNextMethod;
+ _getCurrentMethod = bslInterface.GetCurrentMethod;
+ _onDisposeMethod = bslInterface.OnDisposeMethod;
+ }
+
+ public bool MoveNext()
+ {
+ _userObject.CallAsFunction(_moveNextMethod.DispatchId, Array.Empty(), out var result);
+ return result.AsBoolean();
+ }
+
+ public void Reset()
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public BslValue Current
+ {
+ get
+ {
+ _userObject.CallAsFunction(_getCurrentMethod.DispatchId, Array.Empty(), out var result);
+ return (BslValue)result;
+ }
+ }
+
+ object IEnumerator.Current => Current;
+
+ public void Dispose()
+ {
+ if (_onDisposeMethod != null)
+ _userObject.CallAsProcedure(_onDisposeMethod.DispatchId, Array.Empty());
+ }
+
+ public static RuntimeException IncompatibleInterfaceError()
+ {
+ var error = new BilingualString(
+ "Итератор не соответствует интерфейсу итератора",
+ "Iterator doesn't match Iterator interface");
+
+ return new RuntimeException(error);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs
index 058ed8715..08d4d77dc 100644
--- a/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs
+++ b/src/ScriptEngine/Machine/Contexts/UnmanagedCOMWrapperContext.cs
@@ -105,7 +105,7 @@ public override IValue GetPropValue(int propNum)
var result = DispatchUtility.Invoke(Instance, dispId, null);
return CreateIValue(result);
}
- catch (System.Reflection.TargetInvocationException e)
+ catch (TargetInvocationException e)
{
throw e.InnerException ?? e;
}
@@ -149,16 +149,16 @@ public override void SetPropValue(int propNum, IValue newVal)
}
DispatchUtility.InvokeSetProperty(Instance, dispId, argToPass);
}
- catch (System.Reflection.TargetInvocationException e)
+ catch (TargetInvocationException e)
{
throw e.InnerException ?? e;
}
}
- catch (System.MissingMemberException)
+ catch (MissingMemberException)
{
throw PropertyAccessException.PropNotFoundException(prop.Name);
}
- catch (System.MemberAccessException)
+ catch (MemberAccessException)
{
throw PropertyAccessException.PropIsNotWritableException(prop.Name);
}
@@ -174,8 +174,11 @@ public override int GetMethodNumber(string name)
public override BslMethodInfo GetMethodInfo(int methodNumber)
{
- //TODO: Доработать RcwMethodMetadata
- return BslMethodBuilder.Create().Build();
+ var md = _methods[methodNumber];
+ return BslMethodBuilder.Create()
+ .Name(md.Name)
+ .ReturnType(md.IsFunction ?? true ? typeof(IValue) : typeof(void))
+ .Build();
}
private MethodSignature GetMethodDescription(int methodNumber)
@@ -200,12 +203,12 @@ public override void CallAsProcedure(int methodNumber, IValue[] arguments)
DispatchUtility.Invoke(Instance, dispId, argsData.values, argsData.flags);
RemapOutputParams(arguments, argsData.values, argsData.flags[0], initialValues);
}
- catch (System.Reflection.TargetInvocationException e)
+ catch (TargetInvocationException e)
{
throw e.InnerException ?? e;
}
}
- catch (System.MissingMemberException)
+ catch (MissingMemberException)
{
throw RuntimeException.MethodNotFoundException(method.Name);
}
@@ -231,12 +234,12 @@ public override void CallAsFunction(int methodNumber, IValue[] arguments, out IV
RemapOutputParams(arguments, argsData.values, argsData.flags[0], initialValues);
retValue = CreateIValue(result);
}
- catch (System.Reflection.TargetInvocationException e)
+ catch (TargetInvocationException e)
{
throw e.InnerException ?? e;
}
}
- catch (System.MissingMemberException)
+ catch (MissingMemberException)
{
throw RuntimeException.MethodNotFoundException(method.Name);
}
@@ -247,7 +250,10 @@ private void RemapOutputParams(IValue[] arguments, object[] values, ParameterMod
{
for (int i = 0; i < arguments.Length; i++)
{
- if (flags[i] && !initialValues[i].Equals(values[i]))
+ var initialValue = initialValues[i];
+ var valueAfterCall = values[i];
+
+ if (flags[i] && !Equals(initialValue, valueAfterCall))
{
var variable = (IVariable)arguments[i];
variable.Value = CreateIValue(values[i]);
@@ -257,28 +263,28 @@ private void RemapOutputParams(IValue[] arguments, object[] values, ParameterMod
private bool TryFindMethod(string name, out RcwMethodMetadata md)
{
- if (_methods.Names.TryGetValue(name, out md))
+ if (_methods.ByName.TryGetValue(name, out md))
return true;
if (!DispatchUtility.TryGetDispId(Instance, name, out var dispatchId))
return false;
_methods.Add(new RcwMethodMetadata(name, dispatchId, null));
- md = _methods.DispatchIds[dispatchId];
+ md = _methods.ByDispatchId[dispatchId];
return true;
}
private bool TryFindProperty(string name, out RcwPropertyMetadata md)
{
- if (_props.Names.TryGetValue(name, out md))
+ if (_props.ByName.TryGetValue(name, out md))
return true;
if (!DispatchUtility.TryGetDispId(Instance, name, out var dispatchId))
return false;
_props.Add(new RcwPropertyMetadata(name, dispatchId));
- md = _props.DispatchIds[dispatchId];
+ md = _props.ByDispatchId[dispatchId];
return true;
}
diff --git a/src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs b/src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs
new file mode 100644
index 000000000..bc6833aac
--- /dev/null
+++ b/src/ScriptEngine/Machine/Contexts/UserIterableContextInstance.cs
@@ -0,0 +1,66 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using OneScript.Contexts;
+using OneScript.Exceptions;
+using OneScript.Execution;
+using OneScript.Localization;
+using OneScript.Types;
+using OneScript.Values;
+using ScriptEngine.Machine.Interfaces;
+
+namespace ScriptEngine.Machine.Contexts
+{
+ public class UserIterableContextInstance : UserScriptContextInstance, ICollectionContext
+ {
+ private BslScriptMethodInfo _getCountMethod;
+ private BslScriptMethodInfo _getIteratorMethod;
+ public static readonly BilingualString GetIteratorTerms = new BilingualString("ПолучитьИтератор", "GetIterator");
+ public static readonly BilingualString GetCountTerms = new BilingualString("Количество", "Count");
+
+ public UserIterableContextInstance(IExecutableModule module, TypeDescriptor asObjectOfType, IValue[] args = null) : base(module, asObjectOfType, args)
+ {
+ var methods = module.GetInterface();
+ _getIteratorMethod = methods.GetIteratorMethod;
+ _getCountMethod = methods.GetCountMethod;
+ }
+
+ public int Count()
+ {
+ if (_getCountMethod == null)
+ throw new RuntimeException(
+ new BilingualString(
+ "Класс не поддерживает получение количества элементов, т.к. в нем отсутствует метод "+GetCountTerms.Russian+"()",
+ "Class doesn't support items counting, because method "+GetCountTerms.English+"() is not defined")
+ );
+
+ CallAsFunction(_getCountMethod.DispatchId, Array.Empty(), out var ret);
+
+ return (int)ret.AsNumber();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ CallAsFunction(_getIteratorMethod.DispatchId, Array.Empty(), out var enumerator);
+ if (!(enumerator is UserScriptContextInstance userObject))
+ {
+ throw ScriptedEnumeratorWrapper.IncompatibleInterfaceError();
+ }
+
+ return new ScriptedEnumeratorWrapper(userObject);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs b/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs
index 0d715d8cd..0c980cb07 100644
--- a/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs
+++ b/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs
@@ -14,6 +14,7 @@ This Source Code Form is subject to the terms of the
using OneScript.Contexts;
using OneScript.Exceptions;
using OneScript.Execution;
+using OneScript.Localization;
using OneScript.Types;
using OneScript.Values;
@@ -22,14 +23,21 @@ namespace ScriptEngine.Machine.Contexts
[ContextClass("Сценарий", "Script")]
public class UserScriptContextInstance : ThisAwareScriptedObjectBase, IDebugPresentationAcceptor
{
+ public static readonly BilingualString OnInstanceCreationTerms =
+ new BilingualString("ПриСозданииОбъекта", "OnObjectCreate");
+
+ public static readonly BilingualString PresentationGetProcessingTerms =
+ new BilingualString("ОбработкаПолученияПредставления", "PresentationGetProcessing");
+
+ public static readonly BilingualString RaiseEventTerms =
+ new BilingualString("ВызватьСобытие", "RaiseEvent");
+
+ private const int RAIZEEVENT_INDEX = 0;
+
Dictionary _ownPropertyIndexes;
List _ownProperties;
private Func _asStringOverride;
-
- private const string RAISEEVENT_RU = "ВызватьСобытие";
- private const string RAISEEVENT_EN = "RaiseEvent";
- private const int RAIZEEVENT_INDEX = 0;
public IValue[] ConstructorParams { get; private set; }
@@ -56,7 +64,7 @@ protected override void OnInstanceCreation()
ActivateAsStringOverride();
base.OnInstanceCreation();
- var methId = GetScriptMethod("ПриСозданииОбъекта", "OnObjectCreate");
+ var methId = GetScriptMethod(OnInstanceCreationTerms.Russian, OnInstanceCreationTerms.English);
int constructorParamsCount = ConstructorParams.Count();
if (methId > -1)
@@ -88,12 +96,12 @@ protected override void OnInstanceCreation()
private void ActivateAsStringOverride()
{
- var methId = GetScriptMethod("ОбработкаПолученияПредставления", "PresentationGetProcessing");
+ var methId = GetScriptMethod(PresentationGetProcessingTerms.Russian, PresentationGetProcessingTerms.English);
if (methId == -1)
_asStringOverride = base.ConvertToString;
else
{
- var signature = GetMethodInfo(methId);
+ var signature = GetMethodInfo(GetOwnMethodCount()+methId);
if (signature.GetParameters().Length != 2)
throw new RuntimeException("Обработчик получения представления должен иметь 2 параметра");
@@ -150,13 +158,7 @@ protected override int GetOwnMethodCount()
protected override int FindOwnMethod(string name)
{
- if (string.Equals(RAISEEVENT_EN, name, StringComparison.OrdinalIgnoreCase)
- || string.Equals(RAISEEVENT_RU, name, StringComparison.OrdinalIgnoreCase))
- {
- return RAIZEEVENT_INDEX;
- }
-
- return base.FindOwnMethod(name);
+ return RaiseEventTerms.HasName(name) ? RAIZEEVENT_INDEX : base.FindOwnMethod(name);
}
protected override int FindOwnProperty(string name)
@@ -210,7 +212,7 @@ private static void PrepareCompilation(CompileTimeSymbolsProvider provider, Symb
private static BslMethodInfo[] GetOwnMethodsDefinition()
{
var methodBuilder = BslMethodBuilder.Create();
- methodBuilder.SetNames(RAISEEVENT_RU, RAISEEVENT_EN)
+ methodBuilder.SetNames(RaiseEventTerms.Russian, RaiseEventTerms.English)
.DeclaringType(typeof(UserScriptContextInstance));
methodBuilder.NewParameter()
diff --git a/src/ScriptEngine/Machine/DefaultTypeManager.cs b/src/ScriptEngine/Machine/DefaultTypeManager.cs
index 3be4bd521..985ad9170 100644
--- a/src/ScriptEngine/Machine/DefaultTypeManager.cs
+++ b/src/ScriptEngine/Machine/DefaultTypeManager.cs
@@ -143,6 +143,11 @@ public bool IsKnownType(string typeName)
return _knownTypes.Any(x => x.Name.ToUpperInvariant() == nameToUpper);
}
+ public IReadOnlyList RegisteredTypes()
+ {
+ return _knownTypes;
+ }
+
public Type NewInstanceHandler
{
get
diff --git a/src/ScriptEngine/Machine/Interfaces/InterfaceRegistrationExtensions.cs b/src/ScriptEngine/Machine/Interfaces/InterfaceRegistrationExtensions.cs
new file mode 100644
index 000000000..a5ae0336c
--- /dev/null
+++ b/src/ScriptEngine/Machine/Interfaces/InterfaceRegistrationExtensions.cs
@@ -0,0 +1,39 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using OneScript.Contexts;
+using OneScript.DependencyInjection;
+using OneScript.Execution;
+using OneScript.Language.SyntaxAnalysis;
+
+namespace ScriptEngine.Machine.Interfaces
+{
+ public static class InterfaceRegistrationExtensions
+ {
+ public static IServiceDefinitions EnablePredefinedIterables(this IServiceDefinitions services)
+ {
+ services.RegisterEnumerable();
+ services.RegisterEnumerable();
+ services.RegisterEnumerable();
+
+ return services;
+ }
+
+ public static void AddInterface(this IExecutableModule module, T interfaceData) where T : class
+ {
+ module.Interfaces[typeof(T)] = interfaceData;
+ }
+
+ public static T GetInterface(this IExecutableModule module) where T : class
+ {
+ if (!module.Interfaces.TryGetValue(typeof(T), out var value))
+ return null;
+
+ return (T)value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Interfaces/IterableBslInterface.cs b/src/ScriptEngine/Machine/Interfaces/IterableBslInterface.cs
new file mode 100644
index 000000000..192d0d462
--- /dev/null
+++ b/src/ScriptEngine/Machine/Interfaces/IterableBslInterface.cs
@@ -0,0 +1,23 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using OneScript.Contexts;
+
+namespace ScriptEngine.Machine.Interfaces
+{
+ public class IterableBslInterface
+ {
+ public IterableBslInterface(BslScriptMethodInfo getIteratorMethod, BslScriptMethodInfo getCountMethod)
+ {
+ GetIteratorMethod = getIteratorMethod;
+ GetCountMethod = getCountMethod;
+ }
+
+ public BslScriptMethodInfo GetIteratorMethod { get; }
+ public BslScriptMethodInfo GetCountMethod { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Interfaces/IterableBslInterfaceChecker.cs b/src/ScriptEngine/Machine/Interfaces/IterableBslInterfaceChecker.cs
new file mode 100644
index 000000000..e649c3a68
--- /dev/null
+++ b/src/ScriptEngine/Machine/Interfaces/IterableBslInterfaceChecker.cs
@@ -0,0 +1,73 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using OneScript.Contexts;
+using OneScript.Exceptions;
+using OneScript.Execution;
+using OneScript.Localization;
+using ScriptEngine.Machine.Contexts;
+
+namespace ScriptEngine.Machine.Interfaces
+{
+ internal class IterableBslInterfaceChecker : IPredefinedInterfaceChecker
+ {
+ public static readonly BilingualString IterableAnnotation = new BilingualString("Обходимое", "Iterable");
+
+ public IEnumerable GetRegistrations()
+ {
+ return new[]
+ {
+ PredefinedInterfaceRegistration.OnMethod(IterableAnnotation, UserScriptContextInstance.OnInstanceCreationTerms),
+ PredefinedInterfaceRegistration.OnModule(IterableAnnotation)
+ };
+ }
+
+ public void Validate(IExecutableModule module)
+ {
+ var error = new BilingualString(
+ "Модуль объекта Обходимое должен содержать функцию " + UserIterableContextInstance.GetIteratorTerms.Russian + "()",
+ "Module of Iterable must contain function " + UserIterableContextInstance.GetIteratorTerms.English + "()");
+
+ BslScriptMethodInfo getIteratorMethod;
+
+ try
+ {
+ getIteratorMethod = (BslScriptMethodInfo)module.Methods.Single(method =>
+ UserIterableContextInstance.GetIteratorTerms.HasName(method.Name));
+ }
+ catch (InvalidOperationException e)
+ {
+ throw new InterfaceCheckException(error, e);
+ }
+
+ if (!getIteratorMethod.IsFunction() || getIteratorMethod.GetBslParameters().Length != 0)
+ {
+ throw new InterfaceCheckException(error);
+ }
+
+ BslScriptMethodInfo getCountMethod = (BslScriptMethodInfo)module.Methods.FirstOrDefault(method =>
+ UserIterableContextInstance.GetCountTerms.HasName(method.Name));
+
+ if (getCountMethod != null)
+ {
+ var countError = new BilingualString(
+ "Метод " + UserIterableContextInstance.GetCountTerms.Russian + " должен быть функцией без параметров",
+ "Method " + UserIterableContextInstance.GetCountTerms.English + "() must be a function without parameters");
+
+ if (!getCountMethod.IsFunction() || getCountMethod.GetBslParameters().Length != 0)
+ {
+ throw new InterfaceCheckException(countError);
+ }
+ }
+
+ module.AddInterface(new IterableBslInterface(getIteratorMethod, getCountMethod));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Interfaces/IterablesModuleAnnotationsHandler.cs b/src/ScriptEngine/Machine/Interfaces/IterablesModuleAnnotationsHandler.cs
new file mode 100644
index 000000000..620d9b226
--- /dev/null
+++ b/src/ScriptEngine/Machine/Interfaces/IterablesModuleAnnotationsHandler.cs
@@ -0,0 +1,27 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System.Collections.Generic;
+using OneScript.Language;
+using OneScript.Language.SyntaxAnalysis;
+using OneScript.Localization;
+
+namespace ScriptEngine.Machine.Interfaces
+{
+ public class IterablesModuleAnnotationsHandler : SingleWordModuleAnnotationHandler
+ {
+ private static HashSet SupportedNames = new HashSet()
+ {
+ IterableBslInterfaceChecker.IterableAnnotation,
+ IteratorBslInterfaceChecker.IterableAnnotation
+ };
+
+ public IterablesModuleAnnotationsHandler(IErrorSink errorSink) : base(SupportedNames, errorSink)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Interfaces/IteratorBslInterface.cs b/src/ScriptEngine/Machine/Interfaces/IteratorBslInterface.cs
new file mode 100644
index 000000000..e80481ef5
--- /dev/null
+++ b/src/ScriptEngine/Machine/Interfaces/IteratorBslInterface.cs
@@ -0,0 +1,25 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using OneScript.Contexts;
+
+namespace ScriptEngine.Machine.Interfaces
+{
+ public class IteratorBslInterface
+ {
+ public IteratorBslInterface(BslScriptMethodInfo moveNextMethod, BslScriptMethodInfo getCurrentMethod, BslScriptMethodInfo onDisposeMethod)
+ {
+ MoveNextMethod = moveNextMethod;
+ GetCurrentMethod = getCurrentMethod;
+ OnDisposeMethod = onDisposeMethod;
+ }
+
+ public BslScriptMethodInfo MoveNextMethod { get; }
+ public BslScriptMethodInfo GetCurrentMethod { get; }
+ public BslScriptMethodInfo OnDisposeMethod { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs b/src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs
new file mode 100644
index 000000000..35c3315e1
--- /dev/null
+++ b/src/ScriptEngine/Machine/Interfaces/IteratorBslInterfaceChecker.cs
@@ -0,0 +1,102 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using OneScript.Contexts;
+using OneScript.Exceptions;
+using OneScript.Execution;
+using OneScript.Localization;
+using ScriptEngine.Machine.Contexts;
+
+namespace ScriptEngine.Machine.Interfaces
+{
+ internal class IteratorBslInterfaceChecker : IPredefinedInterfaceChecker
+ {
+ public static readonly BilingualString IterableAnnotation = new BilingualString("Итератор", "Iterator");
+
+ private static readonly BilingualString
+ MoveNextMethodName = new BilingualString("Следующий", "Next");
+
+ private static readonly BilingualString
+ GetCurrentMethodName = new BilingualString("ТекущийЭлемент", "CurrentItem");
+
+ private static readonly BilingualString
+ DisposeMethodName = new BilingualString("ПриОсвобожденииОбъекта", "OnDispose");
+
+ public IEnumerable GetRegistrations()
+ {
+ return new[]
+ {
+ PredefinedInterfaceRegistration.OnMethod(IterableAnnotation, UserScriptContextInstance.OnInstanceCreationTerms),
+ PredefinedInterfaceRegistration.OnModule(IterableAnnotation)
+ };
+ }
+
+ public void Validate(IExecutableModule module)
+ {
+ CheckModule(module);
+ }
+
+ internal static IteratorBslInterface CheckModule(IExecutableModule module)
+ {
+ var moveNextMethod = FindRequiredMethod(module, MoveNextMethodName);
+ var getCurrentMethod = FindRequiredMethod(module, GetCurrentMethodName);
+ var onDisposeMethod = FindOptionalMethod(module, DisposeMethodName);
+
+ if (!moveNextMethod.IsFunction() || moveNextMethod.GetBslParameters().Length != 0)
+ {
+ throw MissingMethod(MoveNextMethodName);
+ }
+
+ if (!getCurrentMethod.IsFunction() || getCurrentMethod.GetBslParameters().Length != 0)
+ {
+ throw MissingMethod(GetCurrentMethodName);
+ }
+
+ if (onDisposeMethod != null && onDisposeMethod.GetBslParameters().Length != 0)
+ {
+ throw MissingMethod(DisposeMethodName);
+ }
+
+ var bslInterface = new IteratorBslInterface(moveNextMethod, getCurrentMethod, onDisposeMethod);
+ module.AddInterface(bslInterface);
+
+ return bslInterface;
+ }
+
+ private static BslScriptMethodInfo FindRequiredMethod(IExecutableModule module, BilingualString names)
+ {
+ try
+ {
+ return (BslScriptMethodInfo)module.Methods.Single(m =>
+ names.HasName(m.Name));
+ }
+ catch (InvalidOperationException e)
+ {
+ throw MissingMethod(names, e);
+ }
+ }
+
+ private static BslScriptMethodInfo FindOptionalMethod(IExecutableModule module,BilingualString names)
+ {
+ return (BslScriptMethodInfo)module.Methods.FirstOrDefault(m =>
+ names.HasName(m.Name));
+
+ }
+
+ private static InterfaceCheckException MissingMethod(BilingualString methodName, Exception parent = null)
+ {
+ var error = new BilingualString(
+ "Обязательный метод "+methodName.Russian+" отсутствует, или не соответствует интерфейсу итератора",
+ "Required method "+methodName.English+" is missing or doesn't match iterator interface");
+
+ return new InterfaceCheckException(error, parent);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ScriptEngine/Machine/StackRuntimeModule.cs b/src/ScriptEngine/Machine/StackRuntimeModule.cs
index b1bf5374a..c507fef5f 100644
--- a/src/ScriptEngine/Machine/StackRuntimeModule.cs
+++ b/src/ScriptEngine/Machine/StackRuntimeModule.cs
@@ -58,6 +58,8 @@ public BslMethodInfo ModuleBody
public IList Code { get; } = new List(512);
public SourceCode Source { get; set; }
+
+ public IDictionary Interfaces { get; } = new Dictionary();
#endregion
}
diff --git a/src/Tests/OneScript.Core.Tests/ArgumentParserTests.cs b/src/Tests/OneScript.Core.Tests/ArgumentParserTests.cs
index cbca74f67..247713773 100644
--- a/src/Tests/OneScript.Core.Tests/ArgumentParserTests.cs
+++ b/src/Tests/OneScript.Core.Tests/ArgumentParserTests.cs
@@ -1,4 +1,4 @@
-/*----------------------------------------------------------
+/*----------------------------------------------------------
This Source Code Form is subject to the terms of the
Mozilla Public License, v.2.0. If a copy of the MPL
was not distributed with this file, You can obtain one
diff --git a/src/Tests/OneScript.Core.Tests/PredefinedInterfacesTest.cs b/src/Tests/OneScript.Core.Tests/PredefinedInterfacesTest.cs
new file mode 100644
index 000000000..453508d1b
--- /dev/null
+++ b/src/Tests/OneScript.Core.Tests/PredefinedInterfacesTest.cs
@@ -0,0 +1,155 @@
+/*----------------------------------------------------------
+This Source Code Form is subject to the terms of the
+Mozilla Public License, v.2.0. If a copy of the MPL
+was not distributed with this file, You can obtain one
+at http://mozilla.org/MPL/2.0/.
+----------------------------------------------------------*/
+
+using System;
+using System.Collections.Generic;
+using FluentAssertions;
+using Moq;
+using OneScript.Contexts;
+using OneScript.Execution;
+using OneScript.Localization;
+using Xunit;
+
+namespace OneScript.Core.Tests;
+
+public class PredefinedInterfacesTest
+{
+ [Fact]
+ public void Test_CheckerReactsOnModuleAnnotations()
+ {
+ var annotationToSearch = new BilingualString("MyAnno");
+ var checker = new Mock();
+ checker.Setup(x => x.GetRegistrations()).Returns(new[]
+ {
+ PredefinedInterfaceRegistration.OnModule(annotationToSearch),
+ });
+
+ var module = MockModule(mock =>
+ {
+ mock.SetupGet(x => x.ModuleAttributes).Returns(new[]
+ {
+ new BslAnnotationAttribute("MyAnno")
+ });
+
+ mock.SetupGet(x => x.Methods).Returns(Array.Empty());
+ });
+
+ checker.Setup(x => x.Validate(module)).Callback((m) =>
+ {
+ m.Interfaces.Add(typeof(string), "Registered");
+ });
+
+ var resolver = new PredefinedInterfaceResolver(new[] { checker.Object });
+ resolver.Resolve(module);
+
+ module.Interfaces.Should().Contain(KeyValuePair.Create(typeof(string), (object)"Registered"));
+ }
+
+ [Fact]
+ public void Test_CheckerDoesNotReactsOnModuleAnnotations()
+ {
+ var annotationToSearch = new BilingualString("MyAnno");
+ var checker = new Mock();
+ checker.Setup(x => x.GetRegistrations()).Returns(new[]
+ {
+ PredefinedInterfaceRegistration.OnModule(annotationToSearch),
+ });
+
+ var module = MockModule(mock =>
+ {
+ mock.SetupGet(x => x.ModuleAttributes).Returns(Array.Empty());
+ mock.SetupGet(x => x.Methods).Returns(Array.Empty());
+ });
+
+ checker.Setup(x => x.Validate(module)).Callback((m) =>
+ {
+ m.Interfaces.Add(typeof(string), "Registered");
+ });
+
+ var resolver = new PredefinedInterfaceResolver(new[] { checker.Object });
+ resolver.Resolve(module);
+
+ module.Interfaces.Should().BeEmpty();
+ }
+
+ [Fact]
+ public void Test_CheckerReactsOnlyOnceOnManyAnnotations()
+ {
+ var annotationToSearch = new BilingualString("MyAnno");
+ var checker = new Mock();
+ checker.Setup(x => x.GetRegistrations()).Returns(new[]
+ {
+ PredefinedInterfaceRegistration.OnModule(annotationToSearch),
+ PredefinedInterfaceRegistration.OnMethod(annotationToSearch, new BilingualString("MyMethod")),
+ });
+
+ var module = MockModule(mock =>
+ {
+ mock.SetupGet(x => x.ModuleAttributes).Returns(new[]
+ {
+ new BslAnnotationAttribute("MyAnno")
+ });
+
+ var method = BslMethodBuilder.Create()
+ .Name("MyMethod")
+ .SetAnnotations(new[] { new BslAnnotationAttribute("MyAnno") })
+ .Build();
+
+ mock.SetupGet(x => x.Methods).Returns(new BslMethodInfo[] { method });
+ });
+
+ checker.Setup(x => x.Validate(module)).Verifiable();
+
+ var resolver = new PredefinedInterfaceResolver(new[] { checker.Object });
+ resolver.Resolve(module);
+
+ checker.Verify(x => x.Validate(It.IsAny()), Times.Once);
+ }
+
+ [Fact]
+ public void Test_CheckerReactsOnlyOnMethodAnnotations()
+ {
+ var annotationToSearch = new BilingualString("MyAnno");
+ var checker = new Mock();
+ checker.Setup(x => x.GetRegistrations()).Returns(new[]
+ {
+ PredefinedInterfaceRegistration.OnMethod(annotationToSearch, new BilingualString("MyMethod")),
+ });
+
+ var module = MockModule(mock =>
+ {
+ var method = BslMethodBuilder.Create()
+ .Name("MyMethod")
+ .SetAnnotations(new[] { new BslAnnotationAttribute("MyAnno") })
+ .Build();
+
+ mock.SetupGet(x => x.Methods).Returns(new BslMethodInfo[] { method });
+ });
+
+ checker.Setup(x => x.Validate(module)).Callback((m) =>
+ {
+ m.Interfaces.Add(typeof(string), "Registered");
+ });
+
+ var resolver = new PredefinedInterfaceResolver(new[] { checker.Object });
+ resolver.Resolve(module);
+
+ module.Interfaces.Should().Contain(KeyValuePair.Create(typeof(string), (object)"Registered"));
+ }
+
+ private static IExecutableModule MockModule(Action> setup)
+ {
+ var dict = new Dictionary();
+ var moduleMock = new Mock();
+ moduleMock.SetupGet(x => x.Interfaces).Returns(dict);
+
+ setup(moduleMock);
+
+ return moduleMock.Object;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Tests/OneScript.Language.Tests/LexerTests.cs b/src/Tests/OneScript.Language.Tests/LexerTests.cs
index 0d047c52e..2f13ab36c 100644
--- a/src/Tests/OneScript.Language.Tests/LexerTests.cs
+++ b/src/Tests/OneScript.Language.Tests/LexerTests.cs
@@ -586,12 +586,12 @@ public void Syntax_Error_Handling()
Assert.Equal("Б", lex.Content);
}
- [Fact(Skip = "Рефакторинг")]
+ [Fact]
public void New_Exception_Shows_Negative_Line_And_Column()
{
- //var e = new ScriptException();
- //Assert.True(e.LineNumber == -1);
- //Assert.True(e.ColumnNumber == -1);
+ var e = new ScriptException("fake");
+ Assert.True(e.LineNumber == -1);
+ Assert.True(e.ColumnNumber == -1);
}
[Fact]
@@ -633,6 +633,23 @@ public void Lexer_Ignores_Comments()
Assert.Equal("value", lex.Content);
}
+ [Fact]
+ public void Lexer_Extracts_Labels()
+ {
+ string code = "~ImALabel:\n" +
+ " ~LabelRef;";
+ var lexer = GetLexerForCode(code);
+
+ var lex = lexer.NextLexem();
+
+ Assert.Equal(LexemType.Label, lex.Type);
+ Assert.Equal("ImALabel", lex.Content);
+
+ lex = lexer.NextLexem();
+ Assert.Equal(LexemType.LabelRef, lex.Type);
+ Assert.Equal("LabelRef", lex.Content);
+ }
+
private ILexer GetLexerForCode(string code)
{
return new FullSourceLexer
diff --git a/src/Tests/OneScript.Language.Tests/ParserTests.cs b/src/Tests/OneScript.Language.Tests/ParserTests.cs
index ec6144928..41ed6f52a 100644
--- a/src/Tests/OneScript.Language.Tests/ParserTests.cs
+++ b/src/Tests/OneScript.Language.Tests/ParserTests.cs
@@ -1168,6 +1168,206 @@ public void TestLocalExportVar()
});
}
+ [Fact]
+ public void TestAsyncProcedure()
+ {
+ var code =
+ @"Асинх Процедура Проц1()
+ Перем Переменная;
+ КонецПроцедуры";
+
+ var node = ParseModuleAndGetValidator(code);
+ node.Is(NodeKind.MethodsSection);
+
+ var methodNode = node.NextChild().Is(NodeKind.Method);
+
+ methodNode.CurrentNode.RealNode.As().IsAsync.Should().BeTrue();
+ }
+
+ [Fact]
+ public void TestAsyncFunction()
+ {
+ var code =
+ @"Асинх Функция Ф1()
+ Перем Переменная;
+ КонецФункции";
+
+ var node = ParseModuleAndGetValidator(code);
+ node.Is(NodeKind.MethodsSection);
+
+ var methodNode = node.NextChild().Is(NodeKind.Method);
+
+ methodNode.CurrentNode.RealNode.As().IsAsync.Should().BeTrue();
+ }
+
+ [Fact]
+ public void TestAwaitPriority()
+ {
+ var code =
+ @"Асинх Процедура Проц1()
+ А = Ждать Вызов().Поле;
+ КонецПроцедуры";
+
+ var node = ParseModuleAndGetValidator(code);
+ node.Is(NodeKind.MethodsSection);
+
+ var method = node.NextChild().Is(NodeKind.Method);
+ var expression = method.DownTo(NodeKind.Assignment)
+ .NextChildIs(NodeKind.Identifier)
+ .NextChild();
+
+ expression.CurrentNode.RealNode.As().Operation.Should().Be(Token.Await);
+ expression
+ .NextChildIs(NodeKind.DereferenceOperation)
+ .NoMoreChildren();
+ }
+
+ [Fact]
+ public void TestAwaitMustBeInAsyncOnly()
+ {
+ var code =
+ @"Процедура Проц1()
+ Ждать Операция();
+ КонецПроцедуры";
+
+ CatchParsingError(code, errors =>
+ {
+ errors.Single().Description.Should().Contain("Await");
+ });
+ }
+
+ [Fact]
+ public void AwaitIsNotKeywordInNonAsyncContext_Variable()
+ {
+ var code =
+ @"Процедура Проц1()
+ А = Ждать;
+ КонецПроцедуры";
+
+ var validator = ParseModuleAndGetValidator(code)
+ .DownTo(NodeKind.Assignment);
+
+ validator
+ .NextChildIs(NodeKind.Identifier)
+ .NextChildIs(NodeKind.Identifier);
+ }
+
+ [Fact]
+ public void AwaitIsNotKeywordInNonAsyncContext_Method()
+ {
+ var code =
+ @"Процедура Проц1()
+ А = Ждать();
+ КонецПроцедуры";
+
+ var validator = ParseModuleAndGetValidator(code)
+ .DownTo(NodeKind.Assignment);
+
+ validator
+ .NextChildIs(NodeKind.Identifier)
+ .NextChildIs(NodeKind.GlobalCall);
+ }
+
+ [Fact]
+ public void AwaitIsNotKeywordInNonAsyncContext_PropertyName()
+ {
+ var code =
+ @"Процедура Проц1()
+ А = П.Ждать;
+ КонецПроцедуры";
+
+ var validator = ParseModuleAndGetValidator(code)
+ .DownTo(NodeKind.DereferenceOperation);
+
+ validator
+ .NextChildIs(NodeKind.Identifier)
+ .NextChildIs(NodeKind.Identifier);
+ }
+
+ [Fact]
+ public void AwaitIsNotKeywordInNonAsyncContext_MemberMethodName()
+ {
+ var code =
+ @"Процедура Проц1()
+ А = П.Ждать();
+ КонецПроцедуры";
+
+ var validator = ParseModuleAndGetValidator(code)
+ .DownTo(NodeKind.DereferenceOperation);
+
+ validator
+ .NextChildIs(NodeKind.Identifier)
+ .NextChildIs(NodeKind.MethodCall);
+ }
+
+ [Fact]
+ public void Await_In_NonAsync_Expression_Fails()
+ {
+ var code =
+ @"Процедура Проц1()
+ Если Ждать ВтороеСлово Тогда
+ КонецЕсли;
+ КонецПроцедуры";
+
+ CatchParsingError(code, err =>
+ {
+ err.Single().ErrorId.Should().Be("AwaitMustBeInAsyncMethod");
+ });
+ }
+
+ [Fact]
+ public void AwaitRequiresExpression()
+ {
+ var code =
+ @"Асинх Процедура Проц1()
+ А = Ждать;
+ КонецПроцедуры";
+
+ CatchParsingError(code, err => err.Single().ErrorId.Should().Be("ExpressionSyntax"));
+ }
+
+ [Fact]
+ public void DoubleAwaitIsForbidden()
+ {
+ var code =
+ @"Асинх Процедура Проц1()
+ А = Ждать Ждать Б;
+ КонецПроцедуры";
+
+ CatchParsingError(code, err => err.Single().ErrorId.Should().Be("ExpressionSyntax"));
+ }
+
+ [Fact]
+ public void Labels_Can_Appear_In_CodeBlocks()
+ {
+ var code =
+ @"А = 1;
+ ~Метка:
+ Б = 2;
+ ";
+
+ var validator = ParseBatchAndGetValidator(code);
+
+ validator.NextChildIs(NodeKind.Assignment);
+ validator.NextChildIs(NodeKind.Label);
+ validator.NextChildIs(NodeKind.Assignment);
+ }
+
+ [Fact]
+ public void Goto_Can_Appear_In_CodeBlocks()
+ {
+ var code =
+ @"А = 1;
+ Перейти ~Метка;
+ Б = 2;
+ ";
+
+ var validator = ParseBatchAndGetValidator(code);
+
+ validator.NextChildIs(NodeKind.Assignment);
+ validator.NextChildIs(NodeKind.Goto);
+ validator.NextChildIs(NodeKind.Assignment);
+ }
private static void CatchParsingError(string code)
{
diff --git a/src/Tests/OneScript.Language.Tests/TestAstNode.cs b/src/Tests/OneScript.Language.Tests/TestAstNode.cs
index 613371016..e909e7952 100644
--- a/src/Tests/OneScript.Language.Tests/TestAstNode.cs
+++ b/src/Tests/OneScript.Language.Tests/TestAstNode.cs
@@ -31,7 +31,7 @@ public TestAstNode(BslSyntaxNode node)
BinaryOperationNode binary => binary.Operation.ToString(),
UnaryOperationNode unary => unary.Operation.ToString(),
PreprocessorDirectiveNode preproc => preproc.DirectiveName,
- _ => Value
+ _ => nonTerm.ToString()
};
}
else if(node is TerminalNode term)
@@ -39,6 +39,11 @@ public TestAstNode(BslSyntaxNode node)
_childrenLazy = new Lazy>(new TestAstNode[0]);
Value = term.Lexem.Content;
}
+ else
+ {
+ _childrenLazy = new Lazy>(new TestAstNode[0]);
+ Value = node.ToString();
+ }
}
public string Value { get; set; }
diff --git a/src/Tests/OneScript.Language.Tests/TreeValidatorExtensions.cs b/src/Tests/OneScript.Language.Tests/TreeValidatorExtensions.cs
index 93f319b0d..1b246c6cb 100644
--- a/src/Tests/OneScript.Language.Tests/TreeValidatorExtensions.cs
+++ b/src/Tests/OneScript.Language.Tests/TreeValidatorExtensions.cs
@@ -27,6 +27,41 @@ public static SyntaxTreeValidator Is(this SyntaxTreeValidator validator, NodeKin
validator.CurrentNode.Kind.Should().Be(type);
return validator;
}
+
+ public static SyntaxTreeValidator DownTo(this SyntaxTreeValidator validator, NodeKind type)
+ {
+ var node = DownTo(validator.CurrentNode, type);
+ if (node == null)
+ {
+ throw new Exception("No such child: " + type);
+ }
+
+ return new SyntaxTreeValidator(node);
+ }
+
+ private static TestAstNode DownTo(this TestAstNode node, NodeKind type)
+ {
+ if (node.Kind == type)
+ return node;
+
+ if (node.Children.Count == 0)
+ return null;
+
+ foreach (var childNode in node.ChildrenList)
+ {
+ if (childNode.Kind == type)
+ return childNode;
+
+ if (childNode.ChildrenList.Count == 0)
+ continue;
+
+ var result = DownTo(childNode, type);
+ if (result != null)
+ return result;
+ }
+
+ return null;
+ }
public static void Is(this TestAstNode node, NodeKind type)
{
diff --git a/src/Tests/OneScript.Language.Tests/TrieTests.cs b/src/Tests/OneScript.Language.Tests/TrieTests.cs
index f6c137daa..0c476e7d0 100644
--- a/src/Tests/OneScript.Language.Tests/TrieTests.cs
+++ b/src/Tests/OneScript.Language.Tests/TrieTests.cs
@@ -12,9 +12,9 @@ namespace OneScript.Language.Tests
public class TrieTests
{
[Fact]
- public void LexemTrieAdd()
+ public void IdentifiersTrieAdd()
{
- var t = new LexemTrie();
+ var t = new IdentifiersTrie();
t.Add("Иван", 0);
t.Add("Иволга", 1);
@@ -28,7 +28,7 @@ public void LexemTrieAdd()
[Fact]
public void Tokens()
{
- var t = new LexemTrie();
+ var t = new IdentifiersTrie();
t.Add("иначе", 1);
t.Add("иначеесли", 2);
diff --git a/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj b/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj
index cc5e71fe0..e06cd92e7 100644
--- a/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj
+++ b/src/VSCode.DebugAdapter/VSCode.DebugAdapter.csproj
@@ -3,7 +3,7 @@
- net461
+ net48
Exe
VSCode.DebugAdapter.Program
Debug;Release;LinuxDebug
diff --git a/tests/ValueTableIndex.os b/tests/ValueTableIndex.os
new file mode 100644
index 000000000..eb46d3fbf
--- /dev/null
+++ b/tests/ValueTableIndex.os
@@ -0,0 +1,245 @@
+///////////////////////////////////////////////////////////////////////
+//
+// Тест проверки работы таблицы значений
+//
+//
+///////////////////////////////////////////////////////////////////////
+
+Перем юТест;
+
+////////////////////////////////////////////////////////////////////
+// Программный интерфейс
+
+Функция Версия() Экспорт
+ Возврат "0.2";
+КонецФункции
+
+Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
+
+ юТест = ЮнитТестирование;
+ ВсеТесты = Новый Массив;
+
+ ВсеТесты.Добавить("ТестДолжен_СоздатьТаблицуЗначенийСИндексами");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьСтроковоеПредставлениеИндекса");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьПоискСИндексом");
+ ВсеТесты.Добавить("ТестДолжен_ПоведениеИндексовПриУдаленииКолонок");
+ ВсеТесты.Добавить("ТестДолжен_ПоведениеИндексовПриИзмененииЗначенийИндексированныхПолей");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьВыбросИсключений");
+
+ Возврат ВсеТесты;
+
+КонецФункции
+
+Процедура ТестДолжен_СоздатьТаблицуЗначенийСИндексами() Экспорт
+
+ Т = Новый ТаблицаЗначений;
+ Т.Колонки.Добавить("К1");
+ Т.Колонки.Добавить("К2");
+ Т.Колонки.Добавить("К3");
+
+ И1 = Т.Индексы.Добавить("К1");
+ И2 = Т.Индексы.Добавить("К1,К2");
+ И3 = Т.Индексы.Добавить("К1,К2,К3");
+
+ юТест.ПроверитьРавенство(Т.Индексы.Количество(), 3);
+
+ Т.Индексы.Удалить(Т.Индексы[0]);
+ юТест.ПроверитьРавенство(Т.Индексы.Количество(), 2);
+
+ Т.Колонки.К1.Имя = "К_1";
+ юТест.ПроверитьРавенство(Т.Индексы[0][0], "К_1");
+
+ Для Каждого мИндекс Из Т.Индексы Цикл
+
+ Для Каждого мИмяКолонки Из мИндекс Цикл
+
+ Колонка = Т.Колонки.Найти(мИмяКолонки);
+ юТест.ПроверитьНеравенство(Колонка, Неопределено, "Не найдена колонка " + мИмяКолонки);
+
+ КонецЦикла;
+
+ КонецЦикла;
+
+ Т.Индексы.Очистить();
+ юТест.ПроверитьРавенство(Т.Индексы.Количество(), 0);
+
+ ИндексСОдинаковымиПолями = Т.Индексы.Добавить("К2, К2, К2");
+ юТест.ПроверитьРавенство(ИндексСОдинаковымиПолями[0], "К2");
+ юТест.ПроверитьРавенство(ИндексСОдинаковымиПолями[1], "К2");
+ юТест.ПроверитьРавенство(ИндексСОдинаковымиПолями[2], "К2");
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьСтроковоеПредставлениеИндекса() Экспорт
+
+ Т = Новый ТаблицаЗначений;
+ Т.Колонки.Добавить("К1");
+ Т.Колонки.Добавить("К2");
+
+ И1 = Т.Индексы.Добавить("К1");
+ И2 = Т.Индексы.Добавить("К1,К2");
+ И3 = Т.Индексы.Добавить("К1,К2,К2");
+ И4 = Т.Индексы.Добавить("К2,К1,К2");
+
+ юТест.ПроверитьРавенство(Строка(И1), "К1");
+ юТест.ПроверитьРавенство(Строка(И2), "К1, К2");
+ юТест.ПроверитьРавенство(Строка(И3), "К1, К2, К2");
+ юТест.ПроверитьРавенство(Строка(И4), "К2, К1, К2");
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьПоискСИндексом() Экспорт
+
+ Т = Новый ТаблицаЗначений;
+ Т.Колонки.Добавить("К1");
+ Т.Колонки.Добавить("К2");
+ Т.Индексы.Добавить("К1");
+ Т.Индексы.Добавить("К2,К1");
+
+ НекоеБольшоеЧисло = 1000; // не такое уж большое, чтобы тесты проходили быстрее
+ Для Инд = 1 По НекоеБольшоеЧисло Цикл
+
+ НоваяСтрока = Т.Добавить();
+ НоваяСтрока.К1 = НекоеБольшоеЧисло;
+ НоваяСтрока.К2 = Инд;
+ НоваяСтрока.К1 = Инд;
+
+ КонецЦикла;
+
+ НайтиИПроверить(Т, НекоеБольшоеЧисло, "Поиск по индексированному полю");
+
+ Т.Колонки.К1.Имя = "ДругоеИмя";
+ НайтиИПроверить(Т, НекоеБольшоеЧисло, "Переименовали проиндексированную колонку");
+ юТест.ПроверитьРавенство(Т.Индексы[0][0], "ДругоеИмя");
+
+ Т.Колонки.ДругоеИмя.Имя = "К1";
+ НайтиИПроверить(Т, НекоеБольшоеЧисло, "Вернули имя");
+
+ Т.Свернуть("К2, К1");
+ НайтиИПроверить(Т, НекоеБольшоеЧисло, "Свернули 0 раз");
+
+ Т.Свернуть("К2", "К1");
+ НайтиИПроверить(Т, НекоеБольшоеЧисло, "Свернули 1 раз");
+
+ Т.Свернуть("К1", "К2");
+ НайтиИПроверить(Т, НекоеБольшоеЧисло, "Свернули 2 раз");
+
+ Т.Свернуть("К1");
+ НайтиИПроверить(Т, НекоеБольшоеЧисло, "Свернули 3 раз");
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПоведениеИндексовПриУдаленииКолонок() Экспорт
+
+ Т = Новый ТаблицаЗначений;
+ Т.Колонки.Добавить("К1");
+ Т.Добавить().К1 = 1;
+ Т.Добавить().К1 = 2;
+ Т.Добавить().К1 = 3;
+
+ Т.Индексы.Добавить("К1");
+ юТест.ПроверитьРавенство(Строка(Т.Индексы[0]), "К1");
+
+ Т.Колонки.Очистить();
+ юТест.ПроверитьРавенство(Строка(Т.Индексы[0]), ""); // Индекс не удаляется, состав полей пустой
+
+ Т.Колонки.Добавить("К1");
+ Т[0].К1 = 3;
+ Т[1].К1 = 2;
+ Т[2].К1 = 1;
+
+ СтруктураПоиска = Новый Структура("К1", 1);
+ НайденныеСтроки = Т.НайтиСтроки(СтруктураПоиска);
+ юТест.ПроверитьРавенство(НайденныеСтроки.Количество(), 1);
+ юТест.ПроверитьРавенство(НайденныеСтроки[0], Т[2]);
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПоведениеИндексовПриИзмененииЗначенийИндексированныхПолей() Экспорт
+
+ Т = Новый ТаблицаЗначений;
+ Т.Колонки.Добавить("К1");
+ Т.Колонки.Добавить("К2");
+ Т.Индексы.Добавить("К2");
+ Т.Индексы.Добавить("К2, К1");
+ Т.Индексы.Добавить("К1");
+ Т.Добавить().К1 = 1;
+ Т.Добавить().К1 = 2;
+ Т.Добавить().К1 = 3;
+
+ Т[0].К1 = 3;
+ Т[1].К1 = 2;
+ Т[2].К1 = 1;
+
+ СтруктураПоиска = Новый Структура("К1", 1);
+ НайденныеСтроки = Т.НайтиСтроки(СтруктураПоиска);
+ юТест.ПроверитьРавенство(НайденныеСтроки.Количество(), 1);
+ юТест.ПроверитьРавенство(НайденныеСтроки[0], Т[2]);
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьВыбросИсключений() Экспорт
+
+ Т = Новый ТаблицаЗначений;
+ Т.Колонки.Добавить("К1");
+ Т.Колонки.Добавить("К2");
+ Т.Индексы.Добавить("К2");
+ Т.Индексы.Добавить("К2, К1");
+ Т.Индексы.Добавить("К1");
+
+ БылоИсключение = Ложь;
+ Попытка
+ Индекс = Т.Индексы[4];
+ Исключение
+ БылоИсключение = Истина;
+ КонецПопытки;
+ юТест.ПроверитьИстину(БылоИсключение, "Доступ за пределы диапазона");
+
+ БылоИсключение = Ложь;
+ Попытка
+ Индекс = Т.Индексы[-1];
+ Исключение
+ БылоИсключение = Истина;
+ КонецПопытки;
+ юТест.ПроверитьИстину(БылоИсключение, "Доступ за пределы диапазона");
+
+ Индекс = Т.Индексы[0];
+ Т.Индексы.Удалить(Индекс);
+ БылоИсключение = Ложь;
+ Попытка
+ Т.Индексы.Удалить(Индекс);
+ Исключение
+ БылоИсключение = Истина;
+ КонецПопытки;
+ юТест.ПроверитьИстину(БылоИсключение, "Удаление несуществующего индекса");
+
+ БылоИсключение = Ложь;
+ Попытка
+ Т.Индексы[0] = Индекс;
+ Исключение
+ БылоИсключение = Истина;
+ КонецПопытки;
+ юТест.ПроверитьИстину(БылоИсключение, "Запись по индексу");
+
+ БылоИсключение = Ложь;
+ Попытка
+ Т.Индексы.Добавить("НесуществующееПоле");
+ Исключение
+ БылоИсключение = Истина;
+ КонецПопытки;
+ юТест.ПроверитьИстину(БылоИсключение, "Индекс по несуществующему полю");
+
+КонецПроцедуры
+
+Процедура НайтиИПроверить(Знач Таблица, Знач ИскомоеЗначение, Знач Пояснение)
+
+ // в проверяемом тесте индексированное поле всегда первое
+ ИндексированноеПоле = Таблица.Колонки[0].Имя;
+
+ Отбор = Новый Структура(ИндексированноеПоле, ИскомоеЗначение);
+ ПоискПоИндексу = Таблица.НайтиСтроки(Отбор);
+
+ юТест.ПроверитьРавенство(ПоискПоИндексу.Количество(), 1, Пояснение);
+ юТест.ПроверитьРавенство(ПоискПоИндексу[0][ИндексированноеПоле], ИскомоеЗначение, Пояснение);
+
+КонецПроцедуры
diff --git a/tests/binary-objects.os b/tests/binary-objects.os
index 130fc076a..aa5bc3a01 100644
--- a/tests/binary-objects.os
+++ b/tests/binary-objects.os
@@ -11,6 +11,7 @@
ВсеТесты = Новый Массив;
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоСоздаетсяБуферДвоичныхДанных");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхНесколькимиБуферами");
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМожноЗаписатьБайты");
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМожноПрочитатьБайты");
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМожноЗаписатьПрочитатьЦелое16");
@@ -30,6 +31,8 @@
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМетодОткрытьПотокДляЧтенияВозвращаетПотокТолькоДляЧтения");
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоХешированиеРаботаетСПотоком");
ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоХешированиеРаботаетСДвоичнымиДанными");
+
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхОднимБуфером");
Возврат ВсеТесты;
@@ -351,3 +354,58 @@
НРег(ПолучитьHexСтрокуИзДвоичныхДанных(Хеширование.ХешСумма)));
КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхОднимБуфером() Экспорт
+
+ Подстроки = Новый Массив;
+ Подстроки.Добавить("Часть1");
+ Подстроки.Добавить("Часть2");
+ Подстроки.Добавить("Часть3");
+ РазделительТекстом = "123";
+
+ ТестовыйБуфер = ПолучитьБуферДвоичныхДанныхИзСтроки(СтрСоединить(Подстроки, РазделительТекстом));
+ Разделитель = ПолучитьБуферДвоичныхДанныхИзСтроки(РазделительТекстом);
+
+ РазделенныеДанные = ТестовыйБуфер.Разделить(Разделитель);
+
+ юТест.ПроверитьРавенство(РазделенныеДанные.Количество(), 3, "два разделителя - три элемента");
+
+ Для Инд = 0 По Подстроки.ВГраница() Цикл
+
+ СтрокаИзБуфера = ПолучитьСтрокуИзБуфераДвоичныхДанных(РазделенныеДанные[Инд]);
+ юТест.ПроверитьРавенство(СтрокаИзБуфера, Подстроки[Инд], "сравнение строк после разделения буфера");
+
+ КонецЦикла;
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьРазделениеБуфераДвоичныхДанныхНесколькимиБуферами() Экспорт
+
+ Подстроки = Новый Массив;
+ Подстроки.Добавить("Часть1");
+ Подстроки.Добавить("Часть2");
+ Подстроки.Добавить("Часть3");
+ Подстроки.Добавить("Часть4");
+ Подстроки.Добавить("Часть5");
+
+ ТестоваяСтрока = "Часть1\R\R\NЧасть2\R\NЧасть3\NЧасть4\RЧасть5";
+
+ ТестовыйБуфер = ПолучитьБуферДвоичныхДанныхИзСтроки(ТестоваяСтрока);
+ Разделители = Новый Массив;
+ Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\N"));
+ Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\R\N"));
+ Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\R"));
+ Разделители.Добавить(ПолучитьБуферДвоичныхДанныхИзСтроки("\R\R\N"));
+
+ РазделенныеДанные = ТестовыйБуфер.Разделить(Разделители);
+
+ юТест.ПроверитьРавенство(РазделенныеДанные.Количество(), 5);
+
+ Для Инд = 0 По РазделенныеДанные.ВГраница() Цикл
+
+ СтрокаИзБуфера = ПолучитьСтрокуИзБуфераДвоичныхДанных(РазделенныеДанные[Инд]);
+ юТест.ПроверитьРавенство(СтрокаИзБуфера, Подстроки[Инд], "сравнение строк после разделения буфера");
+
+ КонецЦикла;
+
+КонецПроцедуры
diff --git a/tests/iterators/annotated_iterator.os b/tests/iterators/annotated_iterator.os
new file mode 100644
index 000000000..b27a2b63a
--- /dev/null
+++ b/tests/iterators/annotated_iterator.os
@@ -0,0 +1,24 @@
+
+Перем Индекс;
+Перем Коллекция;
+Перем Размер;
+
+&Итератор
+Процедура ПриСозданииОбъекта(пКоллекция)
+ Коллекция = пКоллекция;
+ Индекс = 0;
+ Размер = Коллекция.Количество();
+КонецПроцедуры
+
+Функция Следующий()
+ Если Индекс < Размер-1 Тогда
+ Индекс = Индекс + 1;
+ Возврат Истина;
+ Иначе
+ Возврат Ложь;
+ КонецЕсли;
+КонецФункции
+
+Функция ТекущийЭлемент()
+ Возврат Коллекция.Получить(Индекс);
+КонецФункции
\ No newline at end of file
diff --git a/tests/iterators/collection.os b/tests/iterators/collection.os
new file mode 100644
index 000000000..25709f27e
--- /dev/null
+++ b/tests/iterators/collection.os
@@ -0,0 +1,17 @@
+#Обходимое
+
+Функция ПолучитьИтератор()
+ Возврат Новый ИтераторКоллекции(ЭтотОбъект);
+КонецФункции
+
+Функция Количество() Экспорт
+ Возврат 10;
+КонецФункции
+
+Функция Получить(Индекс) Экспорт
+ Если Индекс < 10 тогда
+ Возврат Индекс;
+ КонецЕсли;
+
+ ВызватьИсключение "Индекс выходит за границы коллекции";
+КонецФункции
\ No newline at end of file
diff --git a/tests/iterators/collection_method_style.os b/tests/iterators/collection_method_style.os
new file mode 100644
index 000000000..e55a747dd
--- /dev/null
+++ b/tests/iterators/collection_method_style.os
@@ -0,0 +1,20 @@
+
+&Обходимое
+Процедура ПриСозданииОбъекта()
+КонецПроцедуры
+
+Функция ПолучитьИтератор()
+ Возврат Новый ИтераторСАннотацией(ЭтотОбъект);
+КонецФункции
+
+Функция Количество() Экспорт
+ Возврат 10;
+КонецФункции
+
+Функция Получить(Индекс) Экспорт
+ Если Индекс < 10 тогда
+ Возврат Индекс;
+ КонецЕсли;
+
+ ВызватьИсключение "Индекс выходит за границы коллекции";
+КонецФункции
\ No newline at end of file
diff --git a/tests/iterators/iterator.os b/tests/iterators/iterator.os
new file mode 100644
index 000000000..7868e21dc
--- /dev/null
+++ b/tests/iterators/iterator.os
@@ -0,0 +1,23 @@
+
+Перем Индекс;
+Перем Коллекция;
+Перем Размер;
+
+Процедура ПриСозданииОбъекта(пКоллекция)
+ Коллекция = пКоллекция;
+ Индекс = 0;
+ Размер = Коллекция.Количество();
+КонецПроцедуры
+
+Функция Следующий()
+ Если Индекс < Размер-1 Тогда
+ Индекс = Индекс + 1;
+ Возврат Истина;
+ Иначе
+ Возврат Ложь;
+ КонецЕсли;
+КонецФункции
+
+Функция ТекущийЭлемент()
+ Возврат Коллекция.Получить(Индекс);
+КонецФункции
\ No newline at end of file
diff --git a/tests/iterators/test-iterators.os b/tests/iterators/test-iterators.os
new file mode 100644
index 000000000..a54de631a
--- /dev/null
+++ b/tests/iterators/test-iterators.os
@@ -0,0 +1,57 @@
+Перем юТест;
+
+Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
+
+ юТест = ЮнитТестирование;
+
+ ВсеТесты = Новый Массив;
+ ВсеТесты.Добавить("ТестДолжен_ОбойтиКоллекцию");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМодулиСАннотациейКонструктораРаботают");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоИтераторПроверяетсяПриКомпиляции");
+
+ Возврат ВсеТесты;
+
+КонецФункции
+
+Процедура ТестДолжен_ОбойтиКоллекцию() Экспорт
+
+ ТекКаталог = ТекущийСценарий().Каталог;
+
+ ПодключитьСценарий(ОбъединитьПути(ТекКаталог, "iterator.os"), "ИтераторКоллекции");
+ ПодключитьСценарий(ОбъединитьПути(ТекКаталог, "collection.os"), "Коллекция");
+
+ Коллекция = Новый Коллекция;
+
+ Индекс = 1;
+ Для Каждого Элемент Из Коллекция цикл
+ юТест.ПроверитьРавенство(Индекс, Элемент);
+ Индекс = Индекс + 1;
+ КонецЦикла;
+
+ юТест.ПроверитьРавенство(10, Индекс);
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьЧтоМодулиСАннотациейКонструктораРаботают() Экспорт
+
+ ТекКаталог = ТекущийСценарий().Каталог;
+
+ ПодключитьСценарий(ОбъединитьПути(ТекКаталог, "collection_method_style.os"), "КоллекцияСАннотациейМетода");
+ ПодключитьСценарий(ОбъединитьПути(ТекКаталог, "annotated_iterator.os"), "ИтераторСАннотацией");
+
+ Коллекция = Новый КоллекцияСАннотациейМетода;
+
+ Индекс = 1;
+ Для Каждого Элемент Из Коллекция цикл
+ юТест.ПроверитьРавенство(Индекс, Элемент);
+ Индекс = Индекс + 1;
+ КонецЦикла;
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьЧтоИтераторПроверяетсяПриКомпиляции() Экспорт
+
+ Скрипт = "#Итератор
+ |Процедура Привет() КонецПроцедуры";
+
+ юТест.ПроверитьКодСОшибкой(Скрипт, "Обязательный метод Следующий отсутствует");
+КонецПроцедуры
\ No newline at end of file
diff --git a/tests/native-api.os b/tests/native-api.os
index 1f538d95c..bfebd457f 100644
--- a/tests/native-api.os
+++ b/tests/native-api.os
@@ -21,8 +21,6 @@
ЭтоWindows = Истина;
#ИначеЕсли Linux Тогда
ЭтоWindows = Ложь;
- Каталог = ТекущийСценарий().Каталог + "/native-api/";
- ЗапуститьПриложение(Каталог + "build.sh", Каталог, Истина);
#Иначе
Возврат Новый Массив; // под макос не тестируем
#КонецЕсли
diff --git a/tests/reflector.os b/tests/reflector.os
index beb8820c7..7973d1ca4 100644
--- a/tests/reflector.os
+++ b/tests/reflector.os
@@ -24,6 +24,9 @@
ВсеТесты.Добавить("ТестДолжен_ПроверитьМетод_ПолучитьТаблицуСвойств");
ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовМетодаСПараметрамиПоУмолчанию");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовМетодаБезПараметровПоУмолчанию");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьПередачуПараметровПоУмолчанию");
+
ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодСуществуетДляТипа");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПолучитьТаблицуМетодовДляТипа");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПолучитьТаблицуСвойствДляСистемногоТипа");
@@ -41,6 +44,15 @@
ВсеТесты.Добавить("ТестДолжен_ПроверитьРефлексиюДля_ЭтотОбъект");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПустыеАннотации");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПриватныеПоля");
+
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомКоллекция");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПримитивный");
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПользовательский");
+
+#Если Windows Тогда
+ ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовМетодаComОбъекта");
+#КонецЕсли
Возврат ВсеТесты;
КонецФункции
@@ -215,7 +227,7 @@
ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Пример);
юТест.ПроверитьРавенство(Строка(ТипЗнч(ТаблицаМетодов)), "ТаблицаЗначений", "ТаблицаМетодов");
- юТест.ПроверитьРавенство(6, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()");
+ юТест.ПроверитьРавенство(7, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()");
Метод0 = ТаблицаМетодов.Найти("ВызватьМетод", "Имя");
юТест.ПроверитьНеРавенство(Неопределено, Метод0, "Метод0");
@@ -415,6 +427,47 @@
КонецФункции
+Процедура ТестДолжен_ПроверитьВызовМетодаБезПараметровПоУмолчанию() Экспорт
+ Рефлектор = Новый Рефлектор;
+
+ Массив = Новый Массив(1);
+ Арг = Новый Массив;
+ Арг.Добавить(0);
+
+ Ошибка = Ложь;
+ Попытка
+ Рефлектор.ВызватьМетод(Массив, "Установить", Арг);
+ Ч = Массив[0];
+ Ошибка = Истина;
+ Исключение
+ Сообщение = ОписаниеОшибки();
+ Если СтрНайти(Сообщение,"NullReferenceException") <> 0 Тогда
+ Ошибка = Истина;
+ КонецЕсли;
+ КонецПопытки;
+
+ Если Ошибка Тогда
+ юТест.ТестПровален("Вызов рефлектора с недостаточным количеством параметров без умолчания");
+ КонецЕсли;
+
+КонецПроцедуры
+
+Процедура ТестПередачиПараметровПоУмолчанию(Пар1, Пар2="п2") Экспорт
+ юТест.ПроверитьРавенство(Пар1, "п1", "Тест передачи параметров: параметр 1");
+ юТест.ПроверитьРавенство(Пар2, "п2", "Тест передачи параметров: параметр 2");
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьПередачуПараметровПоУмолчанию() Экспорт
+ Рефлектор = Новый Рефлектор;
+
+ Массив = Новый Массив(1);
+ Арг = Новый Массив;
+ Арг.Добавить("п1");
+ Рефлектор.ВызватьМетод(ЭтотОбъект, "ТестПередачиПараметровПоУмолчанию", Арг);
+
+КонецПроцедуры
+
+
Процедура ТестДолжен_ПроверитьМетодСуществуетДляТипа() Экспорт
Рефлектор = Новый Рефлектор;
@@ -667,4 +720,165 @@
юТест.ПроверитьНеравенство(0, ТаблицаМетодов.Количество());
юТест.ПроверитьНеравенство(0, ТаблицаСвойств.Количество());
-КонецПроцедуры
\ No newline at end of file
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьИзвестныеТипы() Экспорт
+
+ ПолучитьОбъектДляПроверки("МойКлассныйТип");
+
+ Рефлектор = Новый Рефлектор;
+
+ ИзвестныеТипы = Рефлектор.ИзвестныеТипы();
+
+ ПроверитьТипИзвестныхТипов(ИзвестныеТипы);
+
+ Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл
+ ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);
+ КонецЦикла;
+
+ ОписаниеТипаЧисло = ИзвестныеТипы.Найти(Тип("Число"));
+
+ юТест.ПроверитьЗаполненность(ОписаниеТипаЧисло);
+ юТест.ПроверитьТип(ОписаниеТипаЧисло, "СтрокаТаблицыЗначений");
+ юТест.ПроверитьИстину(ОписаниеТипаЧисло.Примитивный);
+ юТест.ПроверитьЛожь(ОписаниеТипаЧисло.Пользовательский);
+ юТест.ПроверитьЛожь(ОписаниеТипаЧисло.Коллекция);
+
+ ОписаниеТипаМассив = ИзвестныеТипы.Найти(Тип("Массив"));
+
+ юТест.ПроверитьЗаполненность(ОписаниеТипаМассив);
+ юТест.ПроверитьТип(ОписаниеТипаМассив, "СтрокаТаблицыЗначений");
+ юТест.ПроверитьЛожь(ОписаниеТипаМассив.Примитивный);
+ юТест.ПроверитьЛожь(ОписаниеТипаМассив.Пользовательский);
+ юТест.ПроверитьИстину(ОписаниеТипаМассив.Коллекция);
+
+ ОписаниеТипаМойКлассныйТип = ИзвестныеТипы.Найти(Тип("МойКлассныйТип"));
+
+ юТест.ПроверитьЗаполненность(ОписаниеТипаМойКлассныйТип);
+ юТест.ПроверитьТип(ОписаниеТипаМойКлассныйТип, "СтрокаТаблицыЗначений");
+ юТест.ПроверитьЛожь(ОписаниеТипаМойКлассныйТип.Примитивный);
+ юТест.ПроверитьИстину(ОписаниеТипаМойКлассныйТип.Пользовательский);
+ юТест.ПроверитьЛожь(ОписаниеТипаМойКлассныйТип.Коллекция);
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомКоллекция() Экспорт
+
+ ПолучитьОбъектДляПроверки("МойКлассныйТип");
+
+ Рефлектор = Новый Рефлектор;
+
+ Отбор = Новый Структура("Коллекция", Истина);
+
+ ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор);
+
+ ПроверитьТипИзвестныхТипов(ИзвестныеТипы);
+
+ Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл
+ ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);
+
+ юТест.ПроверитьИстину(ИзвестныйТип.Коллекция);
+ юТест.ПроверитьЛожь(ИзвестныйТип.Примитивный);
+ юТест.ПроверитьЛожь(ИзвестныйТип.Пользовательский);
+
+ КонецЦикла;
+
+ ОписаниеТипаМассив = ИзвестныеТипы.Найти(Тип("Массив"));
+
+ юТест.ПроверитьЗаполненность(ОписаниеТипаМассив);
+ юТест.ПроверитьТип(ОписаниеТипаМассив, "СтрокаТаблицыЗначений");
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПримитивный() Экспорт
+
+ ПолучитьОбъектДляПроверки("МойКлассныйТип");
+
+ Рефлектор = Новый Рефлектор;
+
+ Отбор = Новый Структура("Примитивный", Истина);
+
+ ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор);
+
+ ПроверитьТипИзвестныхТипов(ИзвестныеТипы);
+
+ Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл
+
+ ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);
+
+ юТест.ПроверитьЛожь(ИзвестныйТип.Коллекция);
+ юТест.ПроверитьИстину(ИзвестныйТип.Примитивный);
+ юТест.ПроверитьЛожь(ИзвестныйТип.Пользовательский);
+
+ КонецЦикла;
+
+ ОписаниеТипаЧисло = ИзвестныеТипы.Найти(Тип("Число"));
+
+ юТест.ПроверитьЗаполненность(ОписаниеТипаЧисло);
+ юТест.ПроверитьТип(ОписаниеТипаЧисло, "СтрокаТаблицыЗначений");
+
+КонецПроцедуры
+
+Процедура ТестДолжен_ПроверитьИзвестныеТипы_СОтборомПользовательский() Экспорт
+
+ ПолучитьОбъектДляПроверки("МойКлассныйТип");
+
+ Рефлектор = Новый Рефлектор;
+
+ Отбор = Новый Структура("Пользовательский", Истина);
+
+ ИзвестныеТипы = Рефлектор.ИзвестныеТипы(Отбор);
+
+ ПроверитьТипИзвестныхТипов(ИзвестныеТипы);
+
+ Для Каждого ИзвестныйТип Из ИзвестныеТипы Цикл
+
+ ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип);
+
+ юТест.ПроверитьЛожь(ИзвестныйТип.Коллекция);
+ юТест.ПроверитьЛожь(ИзвестныйТип.Примитивный);
+ юТест.ПроверитьИстину(ИзвестныйТип.Пользовательский);
+
+ КонецЦикла;
+
+ ОписаниеТипаМойКлассныйТип = ИзвестныеТипы.Найти(Тип("МойКлассныйТип"));
+
+ юТест.ПроверитьЗаполненность(ОписаниеТипаМойКлассныйТип);
+ юТест.ПроверитьТип(ОписаниеТипаМойКлассныйТип, "СтрокаТаблицыЗначений");
+
+КонецПроцедуры
+
+Процедура ПроверитьТипИзвестныхТипов(ИзвестныеТипы)
+
+ юТест.ПроверитьТип(ИзвестныеТипы, "ТаблицаЗначений");
+ юТест.ПроверитьНеРавенство(ИзвестныеТипы.Количество(), 0);
+
+ юТест.ПроверитьРавенство(ИзвестныеТипы.Колонки.Количество(), 5);
+ юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Имя"));
+ юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Значение"));
+ юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Примитивный"));
+ юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Пользовательский"));
+ юТест.ПроверитьЗаполненность(ИзвестныеТипы.Колонки.Найти("Коллекция"));
+
+КонецПроцедуры
+
+Процедура ПроверитьСтрокуИзвестныхТипов(ИзвестныйТип)
+
+ юТест.ПроверитьТип(ИзвестныйТип.Имя, "Строка");
+ юТест.ПроверитьТип(ИзвестныйТип.Значение, "Тип");
+ юТест.ПроверитьТип(ИзвестныйТип.Примитивный, "Булево");
+ юТест.ПроверитьТип(ИзвестныйТип.Пользовательский, "Булево");
+ юТест.ПроверитьТип(ИзвестныйТип.Коллекция, "Булево");
+
+ юТест.ПроверитьЗаполненность(ИзвестныйТип.Имя);
+ юТест.ПроверитьЗаполненность(ИзвестныйТип.Значение);
+
+КонецПроцедуры
+
+#Если Windows Тогда
+Процедура ТестДолжен_ПроверитьВызовМетодаComОбъекта() Экспорт
+ FSO = ПолучитьCOMОбъект("", "Scripting.FileSystemObject");
+ Рез = FSO.DriveExists("C");
+ юТест.ПроверитьТип(Рез, "Булево");
+КонецПроцедуры
+#КонецЕсли
diff --git a/tests/testdata/magic-object.os b/tests/testdata/magic-object.os
index 08ebe52e4..a4bd36228 100644
--- a/tests/testdata/magic-object.os
+++ b/tests/testdata/magic-object.os
@@ -1,6 +1,10 @@
Перем ПроизвольноеПредставление Экспорт;
Перем ЗначПоУмолчанию Экспорт;
+Процедура ПриСозданииОбъекта(Прм1, Прм2, Прм3, Прм4 = 4)
+ ЗначПоУмолчанию = Прм4;
+КонецПроцедуры
+
Процедура ОбработкаПолученияПредставления(Строка, СтандартнаяОбработка)
Если ПроизвольноеПредставление = Неопределено Тогда
@@ -12,6 +16,3 @@
КонецПроцедуры
-Процедура ПриСозданииОбъекта(Прм1, Прм2, Прм3, Прм4 = 4)
- ЗначПоУмолчанию = Прм4;
-КонецПроцедуры