From c64e5ae36073bd6138159694535f85edd582c34e Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Sun, 4 Dec 2016 16:04:07 +0300 Subject: [PATCH 01/63] =?UTF-8?q?CodeStat:=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=BE=D0=B4=D1=81=D1=87=D1=91?= =?UTF-8?q?=D1=82=20=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=81=D1=82=D0=B8=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BA=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Добавлен ключ -codestat= * Сбор количества раз выполнения строки в разрезе модуля, метода и номера строки. * Вывод статистики в JSON --- src/1Script_Mono.sln | 2 +- .../HostedScriptEngine.cs | 13 ++++ .../Machine/CodeStat/CodeStatEntry.cs | 17 +++++ .../Machine/CodeStat/CodeStatProcessor.cs | 69 +++++++++++++++++++ .../Machine/CodeStat/ICodeStatCollector.cs | 14 ++++ src/ScriptEngine/Machine/MachineInstance.cs | 24 +++++++ src/ScriptEngine/ScriptEngine.csproj | 12 ++++ src/ScriptEngine/ScriptingEngine.cs | 4 ++ src/ScriptEngine/packages.config | 4 ++ src/oscript/BehaviorSelector.cs | 38 +++++----- src/oscript/ExecuteScriptBehavior.cs | 5 +- src/oscript/ScriptFileHelper.cs | 13 ++++ src/oscript/ShowUsageBehavior.cs | 2 + tests/process.os | 2 + 14 files changed, 198 insertions(+), 21 deletions(-) create mode 100644 src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs create mode 100644 src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs create mode 100644 src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs create mode 100644 src/ScriptEngine/packages.config diff --git a/src/1Script_Mono.sln b/src/1Script_Mono.sln index 6ec63d255..6d0913aea 100644 --- a/src/1Script_Mono.sln +++ b/src/1Script_Mono.sln @@ -111,7 +111,7 @@ Global $1.ResourceNamePolicy = FileFormatDefault $0.TextStylePolicy = $2 $2.inheritsSet = null - $2.scope = application/config+xml + $2.scope = application/xml $2.FileWidth = 120 $2.inheritsScope = text/plain $0.CSharpFormattingPolicy = $3 diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index 1edf53298..f38006a3f 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -23,6 +23,8 @@ public class HostedScriptEngine bool _isInitialized; bool _configInitialized; + private CodeStatProcessor _codeStat; + public HostedScriptEngine() { _engine = new ScriptingEngine(); @@ -219,5 +221,16 @@ private Process InitProcess(IHostApplication host, ref LoadedModuleHandle module return process; } + public void EnableCodeStatistics(string outputFileName) + { + _codeStat = new CodeStatProcessor(outputFileName); + _engine.SetCodeStatisticsCollector(_codeStat); + } + + public void Finalize() + { + _codeStat?.OutputCodeStat(); + } + } } diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs new file mode 100644 index 000000000..6499012ba --- /dev/null +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs @@ -0,0 +1,17 @@ +/*---------------------------------------------------------- +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; + +namespace ScriptEngine.Machine +{ + public struct CodeStatEntry + { + public string ScriptFileName; + public string SubName; + public int LineNumber; + } +} diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs new file mode 100644 index 000000000..1ad5e86f6 --- /dev/null +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs @@ -0,0 +1,69 @@ +/*---------------------------------------------------------- +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.IO; +using System.Linq; +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace ScriptEngine.Machine +{ + public class CodeStatProcessor : ICodeStatCollector + { + private Dictionary _codeStat = new Dictionary(); + private readonly string _outputFileName; + + public CodeStatProcessor(string fileName) + { + _outputFileName = fileName; + } + + public void MarkEntryReached(CodeStatEntry entry) + { + int oldValue = 0; + _codeStat.TryGetValue(entry, out oldValue); + _codeStat[entry] = oldValue + 1; + } + + public void OutputCodeStat() + { + + var w = new StreamWriter(_outputFileName); + var jwriter = new JsonTextWriter(w); + jwriter.Formatting = Formatting.Indented; + + jwriter.WriteStartObject(); + foreach (var source in _codeStat.GroupBy((arg) => arg.Key.ScriptFileName)) + { + jwriter.WritePropertyName(source.Key, true); + jwriter.WriteStartObject(); + + jwriter.WritePropertyName("path"); + jwriter.WriteValue(source.Key); + foreach (var method in source.GroupBy((arg) => arg.Key.SubName)) + { + jwriter.WritePropertyName(method.Key, true); + jwriter.WriteStartObject(); + + foreach (var entry in method) + { + jwriter.WritePropertyName(entry.Key.LineNumber.ToString()); + jwriter.WriteValue(entry.Value); + } + + jwriter.WriteEndObject(); + } + jwriter.WriteEndObject(); + } + jwriter.WriteEndObject(); + jwriter.Flush(); + + _codeStat.Clear(); + } + } +} diff --git a/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs new file mode 100644 index 000000000..af9d3915d --- /dev/null +++ b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs @@ -0,0 +1,14 @@ +/*---------------------------------------------------------- +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/. +----------------------------------------------------------*/ + +namespace ScriptEngine.Machine +{ + public interface ICodeStatCollector + { + void MarkEntryReached(CodeStatEntry entry); + } +} diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index fd51e7dd7..36a38de7a 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -22,6 +22,7 @@ public class MachineInstance private Stack _exceptionsStack; private Stack _states; private LoadedModule _module; + private ICodeStatCollector _codeStatCollector = null; internal MachineInstance() { @@ -332,6 +333,25 @@ private void ExecuteCode() } } + public void SetCodeStatisticsCollector(ICodeStatCollector collector) + { + _codeStatCollector = collector; + } + + private void AddCodeStatStart() + { + if (_codeStatCollector == null) + return; + + var entry = new CodeStatEntry() { + ScriptFileName = CurrentScript?.Source, + SubName = _currentFrame.MethodName, + LineNumber = _currentFrame.LineNumber + }; + + _codeStatCollector.MarkEntryReached(entry); + } + private void MainCommandLoop() { try @@ -341,6 +361,10 @@ private void MainCommandLoop() { var command = _module.Code[_currentFrame.InstructionPointer]; _commands[(int)command.Code](command.Argument); + + if (command.Code == OperationCode.LineNum) + AddCodeStatStart(); + } } catch (RuntimeException) diff --git a/src/ScriptEngine/ScriptEngine.csproj b/src/ScriptEngine/ScriptEngine.csproj index 3914fb88b..3c02c388d 100644 --- a/src/ScriptEngine/ScriptEngine.csproj +++ b/src/ScriptEngine/ScriptEngine.csproj @@ -83,6 +83,9 @@ + + ..\packages\Newtonsoft.Json.9.0.1\lib\net40\Newtonsoft.Json.dll + @@ -187,6 +190,15 @@ + + + + + + + + + diff --git a/src/ScriptEngine/ScriptingEngine.cs b/src/ScriptEngine/ScriptingEngine.cs index 6547f8b20..62e670942 100644 --- a/src/ScriptEngine/ScriptingEngine.cs +++ b/src/ScriptEngine/ScriptingEngine.cs @@ -142,6 +142,10 @@ public AttachedScriptsFactory AttachedScriptsFactory } } + public void SetCodeStatisticsCollector(ICodeStatCollector collector) + { + _machine.SetCodeStatisticsCollector(collector); + } #region IDisposable Members diff --git a/src/ScriptEngine/packages.config b/src/ScriptEngine/packages.config new file mode 100644 index 000000000..101fdf5c4 --- /dev/null +++ b/src/ScriptEngine/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/oscript/BehaviorSelector.cs b/src/oscript/BehaviorSelector.cs index 3bb95f15e..aefa40ae2 100644 --- a/src/oscript/BehaviorSelector.cs +++ b/src/oscript/BehaviorSelector.cs @@ -27,30 +27,27 @@ public static AppBehavior Select(string[] cmdLineArgs) { var path = cmdLineArgs[0]; return new ExecuteScriptBehavior(path, cmdLineArgs.Skip(1).ToArray()); - } - else if (cmdLineArgs[0].ToLower() == "-measure") + } else if (cmdLineArgs[0].ToLower() == "-measure") { if (cmdLineArgs.Length > 1) { var path = cmdLineArgs[1]; return new MeasureBehavior(path, cmdLineArgs.Skip(2).ToArray()); } - } - else if (cmdLineArgs[0].ToLower() == "-compile") + } else if (cmdLineArgs[0].ToLower() == "-compile") { if (cmdLineArgs.Length > 1) { var path = cmdLineArgs[1]; return new ShowCompiledBehavior(path); } - } - else if (cmdLineArgs[0].ToLower() == "-check") + } else if (cmdLineArgs[0].ToLower() == "-check") { if (cmdLineArgs.Length > 1) { bool cgi_mode = false; int paramIndex = 1; - if (cmdLineArgs [paramIndex].ToLower () == "-cgi") + if (cmdLineArgs[paramIndex].ToLower() == "-cgi") { ++paramIndex; cgi_mode = true; @@ -59,15 +56,14 @@ public static AppBehavior Select(string[] cmdLineArgs) var path = cmdLineArgs[paramIndex]; ++paramIndex; string env = null; - if(cmdLineArgs.Length > paramIndex && cmdLineArgs[paramIndex].StartsWith("-env=")) + if (cmdLineArgs.Length > paramIndex && cmdLineArgs[paramIndex].StartsWith("-env=")) { env = cmdLineArgs[paramIndex].Substring(5); } return new CheckSyntaxBehavior(path, env, cgi_mode); } - } - else if (cmdLineArgs[0].ToLower() == "-make") + } else if (cmdLineArgs[0].ToLower() == "-make") { if (cmdLineArgs.Length == 3) { @@ -75,27 +71,23 @@ public static AppBehavior Select(string[] cmdLineArgs) var output = cmdLineArgs[2]; return new MakeAppBehavior(codepath, output); } - } - else if(cmdLineArgs[0].ToLower() == "-cgi") + } else if (cmdLineArgs[0].ToLower() == "-cgi") { return new CgiBehavior(); - } - else if (cmdLineArgs[0].ToLower() == "-version") + } else if (cmdLineArgs[0].ToLower() == "-version") { return new ShowVersionBehavior(); - } - else if(cmdLineArgs[0].StartsWith("-encoding=")) + } else if (cmdLineArgs[0].StartsWith("-encoding=")) { var prefixLen = ("-encoding=").Length; - if(cmdLineArgs[0].Length > prefixLen) + if (cmdLineArgs[0].Length > prefixLen) { var encValue = cmdLineArgs[0].Substring(prefixLen); Encoding encoding; try { encoding = Encoding.GetEncoding(encValue); - } - catch + } catch { Output.WriteLine("Wrong console encoding"); encoding = null; @@ -106,6 +98,14 @@ public static AppBehavior Select(string[] cmdLineArgs) return Select(cmdLineArgs.Skip(1).ToArray()); } + } else if (cmdLineArgs[0].StartsWith("-codestat=")) { + var prefixLen = ("-codestat=").Length; + if (cmdLineArgs[0].Length > prefixLen) + { + var outputStatFile = cmdLineArgs[0].Substring(prefixLen); + ScriptFileHelper.EnableCodeStatistics(outputStatFile); + return Select(cmdLineArgs.Skip(1).ToArray()); + } } } diff --git a/src/oscript/ExecuteScriptBehavior.cs b/src/oscript/ExecuteScriptBehavior.cs index 674add7fc..8d09fd0d6 100644 --- a/src/oscript/ExecuteScriptBehavior.cs +++ b/src/oscript/ExecuteScriptBehavior.cs @@ -53,7 +53,10 @@ public override int Execute() return 1; } - return process.Start(); + var result = process.Start(); + hostedScript.Finalize(); + + return result; } #region IHostApplication Members diff --git a/src/oscript/ScriptFileHelper.cs b/src/oscript/ScriptFileHelper.cs index 05e16e861..27b9d17ff 100644 --- a/src/oscript/ScriptFileHelper.cs +++ b/src/oscript/ScriptFileHelper.cs @@ -15,6 +15,10 @@ namespace oscript { static class ScriptFileHelper { + + public static bool CodeStatisticsEnabled { get; private set; } + public static string CodeStatisticsFileName { get; private set; } + public static string CustomConfigPath(string scriptPath) { var dir = Path.GetDirectoryName(scriptPath); @@ -25,6 +29,12 @@ public static string CustomConfigPath(string scriptPath) return null; } + public static void EnableCodeStatistics(string fileName) + { + CodeStatisticsEnabled = fileName != null; + CodeStatisticsFileName = fileName; + } + // http://www.cookcomputing.com/blog/archives/000556.html public static bool SetAllowUnsafeHeaderParsing() { @@ -99,6 +109,9 @@ public static void OnBeforeScriptRead(HostedScriptEngine engine) { SetAllowUnsafeHeaderParsing(); } + + if (CodeStatisticsEnabled) + engine.EnableCodeStatistics(CodeStatisticsFileName); } } } diff --git a/src/oscript/ShowUsageBehavior.cs b/src/oscript/ShowUsageBehavior.cs index bf1ce45a5..017dbebd0 100644 --- a/src/oscript/ShowUsageBehavior.cs +++ b/src/oscript/ShowUsageBehavior.cs @@ -27,7 +27,9 @@ public override int Execute() Output.WriteLine(String.Format(" {0,-12}shows compiled module without execution", "-compile")); Output.WriteLine(String.Format(" {0,-12}provides syntax check", "-check")); Output.WriteLine(String.Format(" {0,-12}provides syntax check in CGI-mode", "-check -cgi")); + Output.WriteLine(); Output.WriteLine(String.Format(" {0} set output encoding", "-encoding=")); + Output.WriteLine(String.Format(" {0} write code statistics", "-codestat=")); Output.WriteLine(); Output.WriteLine("III. Build standalone executable: oscript.exe -make "); Output.WriteLine(" Builds a standalone executable module based on script specified"); diff --git a/tests/process.os b/tests/process.os index d567b3f0b..fd120827d 100644 --- a/tests/process.os +++ b/tests/process.os @@ -128,7 +128,9 @@ | -compile shows compiled module without execution | -check provides syntax check | -check -cgi provides syntax check in CGI-mode + | | -encoding= set output encoding + | -codestat= write code statistics | |III. Build standalone executable: oscript.exe -make | Builds a standalone executable module based on script specified From 61105e6316d99f006dc22102c7ddc58ee2ee20ef Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Mon, 5 Dec 2016 11:34:30 +0300 Subject: [PATCH 02/63] =?UTF-8?q?CodeStat:=20=D0=BF=D0=BE=D0=BC=D0=B5?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=20=D0=B7=D0=B0=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2?= =?UTF-8?q?=D0=BE=D0=BA=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Строка, на которой начинается объявление процедуры, обозначается в байт-коде. --- src/ScriptEngine/Compiler/Compiler.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index 0d1dceae0..d2d47ac5a 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -328,6 +328,10 @@ private void BuildSingleMethod() throw CompilerException.UnexpectedOperation(); } + var entryPoint = _module.Code.Count; + // Запоминаем строку, в которой встретилось слово Процедура/Функция + AddCommand(OperationCode.LineNum, _parser.CurrentLine); + #region Method signature // сигнатура if (!IsUserSymbol(ref _lastExtractedLexem)) @@ -427,7 +431,6 @@ private void BuildSingleMethod() #region Body // тело - var entryPoint = _module.Code.Count; try { From d97c3516e28e38c30ec3f3a36b8869c8db2e1c41 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Mon, 5 Dec 2016 13:17:17 +0300 Subject: [PATCH 03/63] =?UTF-8?q?CodeStat:=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D0=B0=20=D0=95=D1=81=D0=BB=D0=B8=20=D0=B8=20?= =?UTF-8?q?=D0=9F=D0=BE=D0=BA=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine/Compiler/Compiler.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index d2d47ac5a..6f5354f99 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -508,6 +508,7 @@ private void BuildCodeBatch() { if (endTokens.Contains(_lastExtractedLexem.Token)) { + AddCommand(OperationCode.LineNum, _parser.CurrentLine); return; } if (_lastExtractedLexem.Token == Token.Semicolon) @@ -610,6 +611,8 @@ private void BuildIfStatement() Code = OperationCode.JmpFalse, Argument = _module.Code.Count }; + AddCommand(OperationCode.LineNum, _parser.CurrentLine); + NextToken(); BuildExpression(Token.Then); PushStructureToken(Token.Else, Token.ElseIf, Token.EndIf); @@ -629,6 +632,8 @@ private void BuildIfStatement() Code = OperationCode.JmpFalse, Argument = _module.Code.Count }; + AddCommand(OperationCode.LineNum, _parser.CurrentLine); + NextToken(); PushStructureToken(Token.EndIf); BuildCodeBatch(); @@ -767,6 +772,7 @@ private void BuildWhileStatement() { NextToken(); var conditionIndex = _module.Code.Count; + AddCommand(OperationCode.LineNum, _parser.CurrentLine); var loopRecord = NestedLoopInfo.New(); loopRecord.startPoint = conditionIndex; _nestedLoops.Push(loopRecord); @@ -779,6 +785,7 @@ private void BuildWhileStatement() BuildCodeBatch(); SetTryBlockFlag(savedTryFlag); PopStructureToken(); + AddCommand(OperationCode.Jmp, conditionIndex); var endLoop = AddCommand(OperationCode.Nop, 0); From 1c7bcc5cc36cb37b9e8d3710b015e9f4112edfdb Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Mon, 5 Dec 2016 13:22:17 +0300 Subject: [PATCH 04/63] =?UTF-8?q?Appveyor:=20=D0=B2=D1=8B=D0=BA=D0=BB?= =?UTF-8?q?=D0=B0=D0=B4=D0=BA=D0=B0=20=D0=B0=D1=80=D1=85=D0=B8=D0=B2=D0=B0?= =?UTF-8?q?=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appveyor.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/appveyor.yml b/appveyor.yml index 6f7b5c309..66a453a14 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,3 +16,9 @@ build: verbosity: minimal test_script: - cmd: appveyor-runtests.cmd +after_build: +- 7z a oscript.zip %APPVEYOR_BUILD_FOLDER%/src/oscript/bin/x86/Release/*.dll +- 7z a oscript.zip %APPVEYOR_BUILD_FOLDER%/src/oscript/bin/x86/Release/*.exe +artifacts: +- path: oscript.zip + name: oscript.zip From 577b03633fde9c086a982f3bed37106fc413ab48 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Mon, 5 Dec 2016 15:35:35 +0300 Subject: [PATCH 05/63] =?UTF-8?q?CodeStat:=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BE=D0=BF=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D1=80=D0=B0=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Номер строки теперь определяется на шаге расчленения текста, а не на шаге компиляции, что предотвращает случаи, когда парсер ускакивает на следующую строку. --- src/ScriptEngine/Compiler/Compiler.cs | 14 +++++++------- src/ScriptEngine/Compiler/Parser.cs | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index 6f5354f99..c3374c516 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -311,6 +311,9 @@ private void HandleDirective(bool codeEntered) private void BuildSingleMethod() { + var entryPoint = _module.Code.Count; + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + if (_lastExtractedLexem.Token == Token.Procedure) { PushStructureToken(Token.EndProcedure); @@ -328,10 +331,6 @@ private void BuildSingleMethod() throw CompilerException.UnexpectedOperation(); } - var entryPoint = _module.Code.Count; - // Запоминаем строку, в которой встретилось слово Процедура/Функция - AddCommand(OperationCode.LineNum, _parser.CurrentLine); - #region Method signature // сигнатура if (!IsUserSymbol(ref _lastExtractedLexem)) @@ -508,7 +507,8 @@ private void BuildCodeBatch() { if (endTokens.Contains(_lastExtractedLexem.Token)) { - AddCommand(OperationCode.LineNum, _parser.CurrentLine); + if (_lastExtractedLexem.LineNumber != 0) + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); return; } if (_lastExtractedLexem.Token == Token.Semicolon) @@ -611,7 +611,7 @@ private void BuildIfStatement() Code = OperationCode.JmpFalse, Argument = _module.Code.Count }; - AddCommand(OperationCode.LineNum, _parser.CurrentLine); + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); NextToken(); BuildExpression(Token.Then); @@ -632,7 +632,7 @@ private void BuildIfStatement() Code = OperationCode.JmpFalse, Argument = _module.Code.Count }; - AddCommand(OperationCode.LineNum, _parser.CurrentLine); + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); NextToken(); PushStructureToken(Token.EndIf); diff --git a/src/ScriptEngine/Compiler/Parser.cs b/src/ScriptEngine/Compiler/Parser.cs index 1228e2eac..94257e6ae 100644 --- a/src/ScriptEngine/Compiler/Parser.cs +++ b/src/ScriptEngine/Compiler/Parser.cs @@ -134,6 +134,7 @@ struct Lexem public LexemType Type; public string Content; public Token Token; + public int LineNumber; public static Lexem Empty() { @@ -215,6 +216,7 @@ public override Lexem ReadNextLexem(ParseIterator iterator) { bool isEndOfText = false; char cs = '\0'; + int currentLine = iterator.CurrentLine; while (true) { if (!isEndOfText) @@ -233,7 +235,8 @@ public override Lexem ReadNextLexem(ParseIterator iterator) { Type = LexemType.Operator, Token = LanguageDef.GetToken(content), - Content = content + Content = content, + LineNumber = currentLine }; } else if (_booleanLiterals.Contains(content)) @@ -241,7 +244,8 @@ public override Lexem ReadNextLexem(ParseIterator iterator) lex = new Lexem() { Type = LexemType.BooleanLiteral, - Content = content + Content = content, + LineNumber = currentLine }; } else if (_undefined.Contains(content)) @@ -249,7 +253,8 @@ public override Lexem ReadNextLexem(ParseIterator iterator) lex = new Lexem() { Type = LexemType.UndefinedLiteral, - Content = content + Content = content, + LineNumber = currentLine }; } @@ -258,7 +263,8 @@ public override Lexem ReadNextLexem(ParseIterator iterator) lex = new Lexem() { Type = LexemType.NullLiteral, - Content = content + Content = content, + LineNumber = currentLine }; } @@ -268,7 +274,8 @@ public override Lexem ReadNextLexem(ParseIterator iterator) { Type = LexemType.Identifier, Content = content, - Token = LanguageDef.GetToken(content) + Token = LanguageDef.GetToken(content), + LineNumber = currentLine }; if (LanguageDef.IsBuiltInFunction(lex.Token)) From 490c3b06961524b01dbc0da58d3e869c2b828666 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Wed, 7 Dec 2016 11:55:43 +0300 Subject: [PATCH 06/63] =?UTF-8?q?CodeStat:=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=BE=D0=B4=D1=81=D1=87?= =?UTF-8?q?=D1=91=D1=82=20=D0=9A=D0=BE=D0=BD=D0=B5=D1=86=D0=95=D1=81=D0=BB?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine/Compiler/Compiler.cs | 16 ++++++++++++---- .../Machine/CodeStat/CodeStatProcessor.cs | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index c3374c516..643bc15d7 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -507,8 +507,6 @@ private void BuildCodeBatch() { if (endTokens.Contains(_lastExtractedLexem.Token)) { - if (_lastExtractedLexem.LineNumber != 0) - AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); return; } if (_lastExtractedLexem.Token == Token.Semicolon) @@ -640,16 +638,26 @@ private void BuildIfStatement() PopStructureToken(); } + int exitIndex; + if (_lastExtractedLexem.Token == Token.EndIf) + { + exitIndex = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + } + else + { + // Вообще, такого быть не должно... + exitIndex = AddCommand(OperationCode.Nop, 0); + } + if (!hasAlternativeBranches) { _module.Code[jumpFalseIndex] = new Command() { Code = OperationCode.JmpFalse, - Argument = _module.Code.Count + Argument = exitIndex }; } - var exitIndex = AddCommand(OperationCode.Nop, 0); foreach (var indexToWrite in exitIndices) { _module.Code[indexToWrite] = new Command() diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs index 1ad5e86f6..53246d81d 100644 --- a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs @@ -50,7 +50,7 @@ public void OutputCodeStat() jwriter.WritePropertyName(method.Key, true); jwriter.WriteStartObject(); - foreach (var entry in method) + foreach (var entry in method.OrderBy((kv) => kv.Key.LineNumber)) { jwriter.WritePropertyName(entry.Key.LineNumber.ToString()); jwriter.WriteValue(entry.Value); From e5cac07d058cc56d7318e319c82eb836b758ee25 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Thu, 8 Dec 2016 12:24:44 +0300 Subject: [PATCH 07/63] =?UTF-8?q?CodeStat:=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=BE=D0=B4=D1=81=D1=87=D1=91?= =?UTF-8?q?=D1=82=20=D1=86=D0=B8=D0=BA=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine/Compiler/Compiler.cs | 35 ++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index 643bc15d7..c6cd2113c 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -705,7 +705,8 @@ private void BuildForEachStatement() NextToken(); BuildExpression(Token.Loop); AddCommand(OperationCode.PushIterator, 0); - var loopBegin = AddCommand(OperationCode.IteratorNext, 0); + var loopBegin = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + AddCommand(OperationCode.IteratorNext, 0); var condition = AddCommand(OperationCode.JmpFalse, -1); BuildLoadVariable(identifier); PushStructureToken(Token.EndLoop); @@ -720,6 +721,9 @@ private void BuildForEachStatement() SetTryBlockFlag(savedTryFlag); PopStructureToken(); + if (_lastExtractedLexem.Token == Token.EndLoop) + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + AddCommand(OperationCode.Jmp, loopBegin); var cmd = _module.Code[condition]; cmd.Argument = AddCommand(OperationCode.StopIterator, 0); @@ -745,9 +749,26 @@ private void BuildCountableForStatement() AddCommand(OperationCode.MakeRawValue, 0); AddCommand(OperationCode.PushTmp, 0); var lastIdx = _module.Code.Count; - AddCommand(OperationCode.Jmp, lastIdx + 4); - // increment - var indexLoopBegin = BuildPushVariable(counter); + int indexLoopBegin = -1; + + // TODO: костыль + if (_lastExtractedLexem.Token == Token.Loop) + { + AddCommand(OperationCode.Jmp, lastIdx + 5); + indexLoopBegin = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + } + else + { + AddCommand(OperationCode.Jmp, lastIdx + 4); + } + + { + // increment + var indexLoopBeginNew = BuildPushVariable(counter); + if (indexLoopBegin == -1) + indexLoopBegin = indexLoopBeginNew; + } + AddCommand(OperationCode.Inc, 0); BuildLoadVariable(counter); @@ -763,6 +784,9 @@ private void BuildCountableForStatement() SetTryBlockFlag(savedTryFlag); PopStructureToken(); + if (_lastExtractedLexem.Token == Token.EndLoop) + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + // jmp to start AddCommand(OperationCode.Jmp, indexLoopBegin); var indexLoopEnd = AddCommand(OperationCode.PopTmp, 1); @@ -794,6 +818,9 @@ private void BuildWhileStatement() SetTryBlockFlag(savedTryFlag); PopStructureToken(); + if (_lastExtractedLexem.Token == Token.EndLoop) + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + AddCommand(OperationCode.Jmp, conditionIndex); var endLoop = AddCommand(OperationCode.Nop, 0); From 1a84324462f0482da6a9d790961c149705950639 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 9 Dec 2016 11:41:02 +0300 Subject: [PATCH 08/63] =?UTF-8?q?CodeStat:=20=D0=9E=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B0=20=D0=BA=D0=BE=D0=BD=D1=86=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ВАЖНО: изменение в байт-коде. Теперь оператор "Возврат" не выполняет непосредственный возврат из метода, а переходит в конец метода на единственную в методе команду Return. --- src/ScriptEngine/Compiler/Compiler.cs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index c6cd2113c..dd29953c8 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -482,7 +482,11 @@ private void DispatchMethodBody() _inMethodScope = true; BuildVariableDefinitions(); _isStatementsDefined = true; + + var codeStart = _module.Code.Count; + BuildCodeBatch(); + if (_isFunctionProcessed) { var undefConst = new ConstDefinition() @@ -494,7 +498,28 @@ private void DispatchMethodBody() AddCommand(OperationCode.PushConst, GetConstNumber(ref undefConst)); } + + var codeEnd = _module.Code.Count; + + if (_lastExtractedLexem.Token == Token.EndProcedure + || _lastExtractedLexem.Token == Token.EndFunction) + { + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + } + AddCommand(OperationCode.Return, 0); + + { + // заменим Return на Jmp <сюда> + for (var i = codeStart; i < codeEnd; i++) + { + if (_module.Code[i].Code == OperationCode.Return) + { + _module.Code[i] = new Command() { Code = OperationCode.Jmp, Argument = codeEnd }; + } + } + } + _isStatementsDefined = false; _inMethodScope = false; } From 1e0a15f0491dd22dad1def5b6dbd31754d80fe9e Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 9 Dec 2016 13:31:28 +0300 Subject: [PATCH 09/63] =?UTF-8?q?CodeStat:=20=D0=BE=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B0=20=D0=9F=D0=BE=D0=BF=D1=8B=D1=82?= =?UTF-8?q?=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine/Compiler/Compiler.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index dd29953c8..55ee5a00b 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -929,18 +929,21 @@ private void BuildTryExceptStatement() SetTryBlockFlag(savedTryFlag); var jmpIndex = AddCommand(OperationCode.Jmp, -1); - CorrectCommandArgument(beginTryIndex, _module.Code.Count); - Assert(_lastExtractedLexem.Token == Token.Exception); - if(StringComparer.OrdinalIgnoreCase.Compare(_lastExtractedLexem.Content, "Exception") == 0) + if (StringComparer.OrdinalIgnoreCase.Compare(_lastExtractedLexem.Content, "Exception") == 0) SystemLogger.Write("WARNING! BREAKING CHANGE: Keyword 'Exception' is not supported anymore. Consider using 'Except'"); + var beginHandler = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + + CorrectCommandArgument(beginTryIndex, beginHandler); + PushStructureToken(Token.EndTry); NextToken(); BuildCodeBatch(); PopStructureToken(); - var endIndex = AddCommand(OperationCode.EndTry, 0); + var endIndex = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + AddCommand(OperationCode.EndTry, 0); CorrectCommandArgument(jmpIndex, endIndex); NextToken(); From 43c0802706cc5853e2be6faf16c79adf862f57cf Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 9 Dec 2016 13:42:11 +0300 Subject: [PATCH 10/63] =?UTF-8?q?AppVeyor:=20=D1=83=D0=B2=D0=B5=D0=BB?= =?UTF-8?q?=D0=B8=D1=87=D0=B5=D0=BD=20=D0=BD=D0=BE=D0=BC=D0=B5=D1=80=20?= =?UTF-8?q?=D0=B2=D1=8B=D0=BF=D1=83=D1=81=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 66a453a14..69602089f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.0.14.{build} +version: 1.0.15.{build} pull_requests: do_not_increment_build_number: true configuration: Release From 6cee921fddc325a7f8a6f65811ca98b0dd1e2d33 Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Fri, 9 Dec 2016 17:06:07 +0300 Subject: [PATCH 11/63] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D1=82=D0=B5=D1=81=D1=82=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B4=D0=B5=D0=BC=D0=BE=D0=BD=D1=81=D1=82=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8=20=D0=B1=D0=B0=D0=B3=D0=B0=20https://github.com/os?= =?UTF-8?q?cript-library/opm/issues/15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/global-new.os | 12 ++++++++++++ tests/testdata/fail.os | 1 + tests/testdata/load-fail.os | 2 ++ 3 files changed, 15 insertions(+) create mode 100644 tests/testdata/fail.os create mode 100644 tests/testdata/load-fail.os diff --git a/tests/global-new.os b/tests/global-new.os index 854500f24..20b34b727 100644 --- a/tests/global-new.os +++ b/tests/global-new.os @@ -19,6 +19,8 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьСозданиеОбъектаВнутриВызоваФункцииБезСкобокВНовый"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСозданиеОбъектаВнутриСозданияДругогоОбъекта"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПробросИсключенияИзЗагруженногоСценария"); + Возврат ВсеТесты; КонецФункции @@ -108,6 +110,16 @@ ПроверитьСозданиеМассива(Объект.М2); КонецПроцедуры +Процедура ТестДолжен_ПроверитьПробросИсключенияИзЗагруженногоСценария() Экспорт + ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; + Попытка + НеверныйСценарий = ЗагрузитьСценарий(ОбъединитьПути(ТекПуть, "testdata", "load-fail.os")); + Исключение + Возврат; + КонецПопытки; + ВызватьИсключение "Ожидали исключения, а его не было!"; +КонецПроцедуры + Функция ПроверкаВызова(Параметр) Возврат Параметр; КонецФункции diff --git a/tests/testdata/fail.os b/tests/testdata/fail.os new file mode 100644 index 000000000..85583f6d4 --- /dev/null +++ b/tests/testdata/fail.os @@ -0,0 +1 @@ +ВызватьИсключение 1; \ No newline at end of file diff --git a/tests/testdata/load-fail.os b/tests/testdata/load-fail.os new file mode 100644 index 000000000..916d36a30 --- /dev/null +++ b/tests/testdata/load-fail.os @@ -0,0 +1,2 @@ +ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; +ЗагрузитьСценарий(ОбъединитьПути(ТекПуть,"fail.os")); From e2ad4b341d4dc36faca95b0df67086004d71217c Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Fri, 9 Dec 2016 17:24:45 +0300 Subject: [PATCH 12/63] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=20=D0=B5=D1=89=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=B4=D0=B5=D0=BC=D0=BE=D0=BD=D1=81=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B1=D0=B0=D0=B3=D0=B0=20htt?= =?UTF-8?q?ps://github.com/oscript-library/opm/issues/15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/global-new.os | 17 ++++++++++++++++- tests/testdata/fail.os | 2 +- tests/testdata/fails/fail-class.os | 3 +++ tests/testdata/fails/lib.config | 3 +++ tests/testdata/load-fail.os | 18 ++++++++++++++++-- 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 tests/testdata/fails/fail-class.os create mode 100644 tests/testdata/fails/lib.config diff --git a/tests/global-new.os b/tests/global-new.os index 20b34b727..05941879d 100644 --- a/tests/global-new.os +++ b/tests/global-new.os @@ -20,6 +20,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьСозданиеОбъектаВнутриСозданияДругогоОбъекта"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПробросИсключенияИзЗагруженногоСценария"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПробросИсключенияИзОбъектаБиблиотеки"); Возврат ВсеТесты; КонецФункции @@ -111,9 +112,23 @@ КонецПроцедуры Процедура ТестДолжен_ПроверитьПробросИсключенияИзЗагруженногоСценария() Экспорт + // Сообщить("ТестДолжен_ПроверитьПробросИсключенияИзЗагруженногоСценария"); ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; Попытка - НеверныйСценарий = ЗагрузитьСценарий(ОбъединитьПути(ТекПуть, "testdata", "load-fail.os")); + Сценарий = ЗагрузитьСценарий(ОбъединитьПути(ТекПуть, "testdata", "load-fail.os")); + Сценарий.МетодСценария(); + Исключение + Возврат; + КонецПопытки; + ВызватьИсключение "Ожидали исключения, а его не было!"; +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПробросИсключенияИзОбъектаБиблиотеки() Экспорт + // Сообщить("ТестДолжен_ПроверитьПробросИсключенияИзОбъектаБиблиотеки"); + ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; + Попытка + Сценарий = ЗагрузитьСценарий(ОбъединитьПути(ТекПуть, "testdata", "load-fail.os")); + Сценарий.МетодОбъектаБиблиотеки(); Исключение Возврат; КонецПопытки; diff --git a/tests/testdata/fail.os b/tests/testdata/fail.os index 85583f6d4..b3f78d160 100644 --- a/tests/testdata/fail.os +++ b/tests/testdata/fail.os @@ -1 +1 @@ -ВызватьИсключение 1; \ No newline at end of file +ВызватьИсключение Новый Файл(ТекущийСценарий().Источник).Имя; diff --git a/tests/testdata/fails/fail-class.os b/tests/testdata/fails/fail-class.os new file mode 100644 index 000000000..208df0785 --- /dev/null +++ b/tests/testdata/fails/fail-class.os @@ -0,0 +1,3 @@ +Процедура Метод() Экспорт + ВызватьИсключение Новый Файл(ТекущийСценарий().Источник).Имя; +КонецПроцедуры \ No newline at end of file diff --git a/tests/testdata/fails/lib.config b/tests/testdata/fails/lib.config new file mode 100644 index 000000000..728a5d7c5 --- /dev/null +++ b/tests/testdata/fails/lib.config @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/testdata/load-fail.os b/tests/testdata/load-fail.os index 916d36a30..da6d779ce 100644 --- a/tests/testdata/load-fail.os +++ b/tests/testdata/load-fail.os @@ -1,2 +1,16 @@ -ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; -ЗагрузитьСценарий(ОбъединитьПути(ТекПуть,"fail.os")); +#Использовать "fails" + + // +Процедура МетодСценария() Экспорт + ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; + ЗагрузитьСценарий(ОбъединитьПути(ТекПуть,"fail.os")); +КонецПроцедуры + +Процедура МетодОбъектаБиблиотеки() Экспорт + // Сообщить("до ТестСценарий = Новый fail;"); + ТестСценарий = Новый fail; + // Сообщить("После ТестСценарий = Новый fail;"); + ТестСценарий.Метод(); + // Сообщить("После ТестСценарий.Метод();"); +КонецПроцедуры + From b939bfdc7722a458f38baef7b0d34139ce1345ec Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Mon, 12 Dec 2016 13:50:15 +0300 Subject: [PATCH 13/63] =?UTF-8?q?CodeStat:=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B2=D1=8B=D0=B7=D1=8B=D0=B2=D0=B0=D0=B2=D1=88?= =?UTF-8?q?=D0=B8=D1=85=D1=81=D1=8F=20=D1=81=D1=82=D1=80=D0=BE=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Machine/CodeStat/CodeStatEntry.cs | 30 +++++++++++-- .../Machine/CodeStat/CodeStatProcessor.cs | 15 ++++++- .../Machine/CodeStat/ICodeStatCollector.cs | 4 +- src/ScriptEngine/Machine/MachineInstance.cs | 43 ++++++++++++++++--- 4 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs index 6499012ba..32140e725 100644 --- a/src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatEntry.cs @@ -10,8 +10,32 @@ namespace ScriptEngine.Machine { public struct CodeStatEntry { - public string ScriptFileName; - public string SubName; - public int LineNumber; + public readonly string ScriptFileName; + public readonly string SubName; + public readonly int LineNumber; + + public CodeStatEntry(string ScriptFileName, string SubName, int LineNumber) + { + this.ScriptFileName = ScriptFileName; + this.SubName = SubName; + this.LineNumber = LineNumber; + } + + public override int GetHashCode() + { + return ScriptFileName.GetHashCode() + SubName.GetHashCode() + LineNumber; + } + + public override bool Equals(object obj) + { + if (obj is CodeStatEntry) + { + var other = (CodeStatEntry)obj; + return ScriptFileName.Equals(other.ScriptFileName, StringComparison.Ordinal) + && SubName.Equals(other.SubName, StringComparison.Ordinal) + && (LineNumber == other.LineNumber); + } + return false; + } } } diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs index 53246d81d..45dc26f20 100644 --- a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs @@ -17,17 +17,28 @@ public class CodeStatProcessor : ICodeStatCollector { private Dictionary _codeStat = new Dictionary(); private readonly string _outputFileName; + private HashSet _preparedScripts = new HashSet(); public CodeStatProcessor(string fileName) { _outputFileName = fileName; } - public void MarkEntryReached(CodeStatEntry entry) + public bool IsPrepared(string ScriptFileName) + { + return _preparedScripts.Contains(ScriptFileName); + } + + public void MarkEntryReached(CodeStatEntry entry, int count = 1) { int oldValue = 0; _codeStat.TryGetValue(entry, out oldValue); - _codeStat[entry] = oldValue + 1; + _codeStat[entry] = oldValue + count; + } + + public void MarkPrepared(string ScriptFileName) + { + _preparedScripts.Add(ScriptFileName); } public void OutputCodeStat() diff --git a/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs index af9d3915d..a8d2f2615 100644 --- a/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs +++ b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs @@ -9,6 +9,8 @@ namespace ScriptEngine.Machine { public interface ICodeStatCollector { - void MarkEntryReached(CodeStatEntry entry); + bool IsPrepared(string ScriptFileName); + void MarkEntryReached(CodeStatEntry entry, int count = 1); + void MarkPrepared(string ScriptFileName); } } diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index 36a38de7a..ba277ad0b 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -297,8 +297,44 @@ private void PrepareMethodExecutionDirect(int methodIndex) SetFrame(frame); } + private void PrepareCodeStatisticsData() + { + foreach (var method in _module.Methods) + { + var instructionPointer = method.EntryPoint; + while (instructionPointer < _module.Code.Length) + { + if (_module.Code[instructionPointer].Code == OperationCode.LineNum) + { + var entry = new CodeStatEntry( + CurrentScript?.Source, + method.Signature.Name, + _module.Code[instructionPointer].Argument + ); + _codeStatCollector.MarkEntryReached(entry, count: 0); + } + + if (_module.Code[instructionPointer].Code == OperationCode.Return) + { + break; + } + + instructionPointer++; + } + } + } + private void ExecuteCode() { + if (_codeStatCollector != null) + { + if (!_codeStatCollector.IsPrepared(CurrentScript?.Source)) + { + PrepareCodeStatisticsData(); + _codeStatCollector.MarkPrepared(CurrentScript?.Source); + } + } + while (true) { try @@ -343,12 +379,7 @@ private void AddCodeStatStart() if (_codeStatCollector == null) return; - var entry = new CodeStatEntry() { - ScriptFileName = CurrentScript?.Source, - SubName = _currentFrame.MethodName, - LineNumber = _currentFrame.LineNumber - }; - + var entry = new CodeStatEntry(CurrentScript?.Source, _currentFrame.MethodName, _currentFrame.LineNumber); _codeStatCollector.MarkEntryReached(entry); } From 10e0b34ef9a0814c78985ac7324beae10d056ea4 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Mon, 12 Dec 2016 14:52:00 +0300 Subject: [PATCH 14/63] =?UTF-8?q?CodeStat:=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=BE=D0=BF=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=BE=D0=BC?= =?UTF-8?q?=D0=B5=D1=80=D0=BE=D0=B2=20=D1=81=D1=82=D1=80=D0=BE=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Были ошибки при определении номера строки в случаях если файл начинался с перевода строки LF. --- src/ScriptEngine/Compiler/ParseIterator.cs | 18 ++++++++---------- src/ScriptEngine/Compiler/SourceCodeIndexer.cs | 6 +++--- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/ScriptEngine/Compiler/ParseIterator.cs b/src/ScriptEngine/Compiler/ParseIterator.cs index 8d3eface6..23865d56b 100644 --- a/src/ScriptEngine/Compiler/ParseIterator.cs +++ b/src/ScriptEngine/Compiler/ParseIterator.cs @@ -17,21 +17,19 @@ class ParseIterator private char _currentSymbol; private readonly string _code; private int _lineCounter = 1; - private readonly List _lineBounds; + private readonly Dictionary _lineBounds; public ParseIterator(string code) { _code = code; - _index = 0; _startPosition = 0; - _lineBounds = new List(); - _lineBounds.Add(0);// first line + _lineBounds = new Dictionary(); - if (_code.Length > 0) - { - _currentSymbol = _code[0]; - } - else + _lineCounter = 1; + _lineBounds.Add(_lineCounter, 0); + + _index = -1; + if (!MoveNext()) _currentSymbol = '\0'; } @@ -109,7 +107,7 @@ public bool MoveNext() if (_currentSymbol == '\n') { _lineCounter++; - _lineBounds.Add(_index + 1); + _lineBounds[_lineCounter] = _index + 1; } return true; } diff --git a/src/ScriptEngine/Compiler/SourceCodeIndexer.cs b/src/ScriptEngine/Compiler/SourceCodeIndexer.cs index a2afaa6a1..8769a3923 100644 --- a/src/ScriptEngine/Compiler/SourceCodeIndexer.cs +++ b/src/ScriptEngine/Compiler/SourceCodeIndexer.cs @@ -14,9 +14,9 @@ namespace ScriptEngine.Compiler class SourceCodeIndexer : ISourceCodeIndexer { private readonly string _code; - private readonly IList _lineBounds; + private readonly IDictionary _lineBounds; - public SourceCodeIndexer(string code, IList lineBounds) + public SourceCodeIndexer(string code, IDictionary lineBounds) { _code = code; _lineBounds = lineBounds; @@ -38,7 +38,7 @@ public string GetCodeLine(int index) private int GetLineBound(int lineNumber) { - return _lineBounds[lineNumber - 1]; + return _lineBounds[lineNumber]; } } From de393c7b10e7e4c6d77fa03e2362dcc936ea0c29 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Tue, 13 Dec 2016 09:52:00 +0300 Subject: [PATCH 15/63] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BE=D0=BF=D0=B5=D1=87=D0=B0?= =?UTF-8?q?=D1=82=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine/Machine/MachineInstance.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index ba277ad0b..3fe12abe3 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -749,17 +749,14 @@ private void Or(int arg) private void CallFunc(int arg) { - bool needsDiscrding = MethodCallImpl(arg, true); - _currentFrame.DiscardReturnValue = needsDiscrding; + bool needsDiscarding = MethodCallImpl(arg, true); + _currentFrame.DiscardReturnValue = needsDiscarding; } private void CallProc(int arg) { bool needsDiscarding = MethodCallImpl(arg, false); - if (needsDiscarding) - _currentFrame.DiscardReturnValue = true; - else - _currentFrame.DiscardReturnValue = false; + _currentFrame.DiscardReturnValue = needsDiscarding; } private bool MethodCallImpl(int arg, bool asFunc) From b6e30f6115f25b3e9567dbd36281627263f478e5 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Tue, 13 Dec 2016 11:21:31 +0300 Subject: [PATCH 16/63] =?UTF-8?q?CodeStat:=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=B7=D0=B0=D0=BC=D0=B5=D1=80=20?= =?UTF-8?q?=D0=B2=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=B2=D1=8B=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Machine/CodeStat/CodeStatProcessor.cs | 50 +++++++++++++++++++ .../Machine/CodeStat/ICodeStatCollector.cs | 3 ++ src/ScriptEngine/Machine/MachineInstance.cs | 25 ++++++++-- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs index 45dc26f20..e5b4a3bbc 100644 --- a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs @@ -7,6 +7,7 @@ This Source Code Form is subject to the terms of the using System; using System.IO; +using System.Diagnostics; using System.Linq; using System.Collections.Generic; using Newtonsoft.Json; @@ -16,6 +17,8 @@ namespace ScriptEngine.Machine public class CodeStatProcessor : ICodeStatCollector { private Dictionary _codeStat = new Dictionary(); + private Dictionary _watchers = new Dictionary(); + private Stopwatch _activeStopwatch = null; private readonly string _outputFileName; private HashSet _preparedScripts = new HashSet(); @@ -34,6 +37,20 @@ public void MarkEntryReached(CodeStatEntry entry, int count = 1) int oldValue = 0; _codeStat.TryGetValue(entry, out oldValue); _codeStat[entry] = oldValue + count; + + if (count == 0) + { + if (!_watchers.ContainsKey(entry)) + { + _watchers.Add(entry, new Stopwatch()); + } + } + else + { + _activeStopwatch?.Stop(); + _activeStopwatch = _watchers[entry]; + _activeStopwatch.Start(); + } } public void MarkPrepared(string ScriptFileName) @@ -43,6 +60,7 @@ public void MarkPrepared(string ScriptFileName) public void OutputCodeStat() { + _activeStopwatch?.Stop(); var w = new StreamWriter(_outputFileName); var jwriter = new JsonTextWriter(w); @@ -64,7 +82,20 @@ public void OutputCodeStat() foreach (var entry in method.OrderBy((kv) => kv.Key.LineNumber)) { jwriter.WritePropertyName(entry.Key.LineNumber.ToString()); + jwriter.WriteStartObject(); + + jwriter.WritePropertyName("count"); jwriter.WriteValue(entry.Value); + + if (_watchers.ContainsKey(entry.Key)) + { + var elapsed = _watchers[entry.Key].ElapsedMilliseconds; + + jwriter.WritePropertyName("time"); + jwriter.WriteValue(elapsed); + } + + jwriter.WriteEndObject(); } jwriter.WriteEndObject(); @@ -76,5 +107,24 @@ public void OutputCodeStat() _codeStat.Clear(); } + + public void StopWatch(CodeStatEntry entry) + { + if (_watchers.ContainsKey(entry)) + { + _watchers[entry].Stop(); + } + } + + public void ResumeWatch(CodeStatEntry entry) + { + _activeStopwatch?.Stop(); + + if (_watchers.ContainsKey(entry)) + { + _activeStopwatch = _watchers[entry]; + _activeStopwatch.Start(); + } + } } } diff --git a/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs index a8d2f2615..294f3bf0d 100644 --- a/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs +++ b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs @@ -12,5 +12,8 @@ public interface ICodeStatCollector bool IsPrepared(string ScriptFileName); void MarkEntryReached(CodeStatEntry entry, int count = 1); void MarkPrepared(string ScriptFileName); + + void StopWatch(CodeStatEntry entry); + void ResumeWatch(CodeStatEntry entry); } } diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index 3fe12abe3..341ce299a 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -216,11 +216,14 @@ private void PushFrame() { if(_currentFrame != null) _callStack.Push(_currentFrame); + + CodeStat_StopFrameStatistics(); } private void PopFrame() { _currentFrame = _callStack.Pop(); + CodeStat_ResumeFrameStatistics(); } private void SetFrame(ExecutionFrame frame) @@ -374,13 +377,27 @@ public void SetCodeStatisticsCollector(ICodeStatCollector collector) _codeStatCollector = collector; } - private void AddCodeStatStart() + private CodeStatEntry CurrentCodeEntry() + { + return new CodeStatEntry(CurrentScript?.Source, _currentFrame.MethodName, _currentFrame.LineNumber); + } + + private void CodeStat_LineReached() { if (_codeStatCollector == null) return; - var entry = new CodeStatEntry(CurrentScript?.Source, _currentFrame.MethodName, _currentFrame.LineNumber); - _codeStatCollector.MarkEntryReached(entry); + _codeStatCollector.MarkEntryReached(CurrentCodeEntry()); + } + + private void CodeStat_StopFrameStatistics() + { + _codeStatCollector?.StopWatch(CurrentCodeEntry()); + } + + private void CodeStat_ResumeFrameStatistics() + { + _codeStatCollector?.ResumeWatch(CurrentCodeEntry()); } private void MainCommandLoop() @@ -394,7 +411,7 @@ private void MainCommandLoop() _commands[(int)command.Code](command.Argument); if (command.Code == OperationCode.LineNum) - AddCodeStatStart(); + CodeStat_LineReached(); } } From 8190516250e0984aab4c0a1d888e5ef4e213535b Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Tue, 13 Dec 2016 12:47:34 +0300 Subject: [PATCH 17/63] =?UTF-8?q?CodeStat:=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=BE?= =?UTF-8?q?=D0=B9=20=D1=82=D0=B5=D1=81=D1=82.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/codestat.os | 230 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 tests/codestat.os diff --git a/tests/codestat.os b/tests/codestat.os new file mode 100644 index 000000000..72771e8fa --- /dev/null +++ b/tests/codestat.os @@ -0,0 +1,230 @@ +Перем юТест; + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + юТест = ЮнитТестирование; + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_ПолучитьПутьКOscript"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиИстинаКонецЕсли"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиЛожьИначеКонецЕсли"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьРаботуЗамераВремени"); + + Возврат ВсеТесты; + +КонецФункции + +Процедура ТестДолжен_ПолучитьПутьКOscript() Экспорт + + Путь = Новый Файл(ПутьОСкрипт()); + + юТест.ПроверитьИстину(Путь.Существует()); + +КонецПроцедуры + +Функция СтрокаЗапускаОСкрипта(Знач ПутьКИсполняемомуМодулю) + + СИ = Новый СистемнаяИнформация; + Если Найти(СИ.ВерсияОС, "Windows") > 0 Тогда + Возврат """" + ПутьКИсполняемомуМодулю + """"; + КонецЕсли; + + Возврат "mono """ + ПутьКИСполняемомуМодулю + """"; + +КонецФункции + +Функция ПолучитьВыводДляСкрипта(Знач ТекстСкрипта) + + ИмяФайлаОСкрипта = ПолучитьИмяВременногоФайла("os"); + + ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаОСкрипта); + ЗаписьТекста.Записать(ТекстСкрипта); + ЗаписьТекста.Закрыть(); + + Возврат ЗапуститьФайлСкрипта(ИмяФайлаОСкрипта); + +КонецФункции + +Функция ЗапуститьФайлСкрипта(Знач ИмяФайлаОСкрипта) + + Перем ИмяФайла, СтрокаЗапуска; + ИмяФайлаВывода = ПолучитьИмяВременногоФайла("txt"); + + Путь = СтрокаЗапускаОСкрипта(ПутьОСкрипт()); + + СИ = Новый СистемнаяИнформация; + Если Найти(СИ.ВерсияОС, "Windows") > 0 Тогда + + ИмяФайлаСистемногоСкриптаЗапуска = ПолучитьИмяВременногоФайла("cmd"); + ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаСистемногоСкриптаЗапуска, КодировкаТекста.Oem); + ЗаписьТекста.ЗаписатьСтроку("@echo off"); + + ЗаписьТекста.ЗаписатьСтроку(Путь + " -codestat=" + ИмяФайлаВывода + " " + ИмяФайлаОСкрипта + " > nul"); + ЗаписьТекста.Закрыть(); + + СтрокаЗапуска = ИмяФайлаСистемногоСкриптаЗапуска; + + Иначе + + ИмяФайлаСистемногоСкриптаЗапуска = ПолучитьИмяВременногоФайла("sh"); + ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаСистемногоСкриптаЗапуска,,,, Символы.ПС); + ЗаписьТекста.ЗаписатьСтроку("bash -s << /dev/null" + ); + ЗаписьТекста.ЗаписатьСтроку("CALLEOF"); + ЗаписьТекста.Закрыть(); + + СтрокаЗапуска = "bash " + ИмяФайлаСистемногоСкриптаЗапуска; + + КонецЕсли; + + Процесс = СоздатьПроцесс(СтрокаЗапуска,,Истина); + Процесс.Запустить(); + + Процесс.ОжидатьЗавершения(); + + Возврат ИмяФайлаВывода; + +КонецФункции + +Функция ПрочитатьЗначение(Знач Чтение) + + Если Не Чтение.Прочитать() Тогда + Возврат Неопределено; + КонецЕсли; + + Если Чтение.ТипТекущегоЗначения = ТипЗначенияJson.НачалоОбъекта Тогда + + Результат = Новый Соответствие; + Пока Истина Цикл + + Если Не Чтение.Прочитать() Тогда + ВызватьИсключение "Неверный JSON" + КонецЕсли; + + Если Чтение.ТипТекущегоЗначения = ТипЗначенияJson.КонецОбъекта Тогда + Прервать; + КонецЕсли; + + Если Чтение.ТипТекущегоЗначения = ТипЗначенияJson.ИмяСвойства Тогда + + ИмяСвойства = Чтение.ТекущееЗначение; + ЗначениеСвойства = ПрочитатьЗначение(Чтение); + Результат.Вставить(ИмяСвойства, ЗначениеСвойства); + + КонецЕсли; + + КонецЦикла; + + Возврат Результат; + + ИначеЕсли Чтение.ТипТекущегоЗначения = ТипЗначенияJson.НачалоМассива Тогда + + Результат = Новый Массив; + // Массивов в выводе быть не должно + Возврат Результат; + + ИначеЕсли Чтение.ТипТекущегоЗначения = ТипЗначенияJson.Null Тогда + + Возврат Null; + + ИначеЕсли Чтение.ТипТекущегоЗначения = ТипЗначенияJson.Ничего Тогда + + Возврат Неопределено; + + ИначеЕсли Чтение.ТипТекущегоЗначения = ТипЗначенияJson.Строка Тогда + + Возврат Чтение.ТекущееЗначение; + + ИначеЕсли Чтение.ТипТекущегоЗначения = ТипЗначенияJson.Число Тогда + + Возврат Чтение.ТекущееЗначение; + + КонецЕсли + +КонецФункции + +Функция ПолучитьДанныеПервогоФайла(Знач Данные) + + Для Каждого мКЗ Из Данные Цикл + + Возврат мКЗ.Значение; + + КонецЦикла; + +КонецФункции + +Процедура ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиИстинаКонецЕсли() Экспорт + + ТекстСкрипта = + "Если Истина Тогда // 1: 1 + | Ф = 1; // 2: 1 + |Иначе // 3: 0 + | Ф = 2; // 4: 0 + |КонецЕсли; // 5: 1 + |" + ; + + ИмяФайлаВывода = ПолучитьВыводДляСкрипта(ТекстСкрипта); + Ч = Новый ЧтениеJson(); + Ч.ОткрытьФайл(ИмяФайлаВывода); + + Данные = ПолучитьДанныеПервогоФайла(ПрочитатьЗначение(Ч)); + юТест.ПроверитьРавенство(Данные["$entry"]["1"]["count"], 1); + юТест.ПроверитьРавенство(Данные["$entry"]["2"]["count"], 1); + юТест.ПроверитьРавенство(Данные["$entry"]["3"]["count"], 0); + юТест.ПроверитьРавенство(Данные["$entry"]["4"]["count"], 0); + юТест.ПроверитьРавенство(Данные["$entry"]["5"]["count"], 1); + +КонецПроцедуры + + +Процедура ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиЛожьИначеКонецЕсли() Экспорт + + ТекстСкрипта = + "Если Ложь Тогда // 1: 1 + | Ф = 1; // 2: 0 + |Иначе // 3: 1 + | Ф = 2; // 4: 1 + |КонецЕсли; // 5: 1 + |" + ; + + ИмяФайлаВывода = ПолучитьВыводДляСкрипта(ТекстСкрипта); + Ч = Новый ЧтениеJson(); + Ч.ОткрытьФайл(ИмяФайлаВывода); + + Данные = ПолучитьДанныеПервогоФайла(ПрочитатьЗначение(Ч)); + юТест.ПроверитьРавенство(Данные["$entry"]["1"]["count"], 1); + юТест.ПроверитьРавенство(Данные["$entry"]["2"]["count"], 0); + юТест.ПроверитьРавенство(Данные["$entry"]["3"]["count"], 1); + юТест.ПроверитьРавенство(Данные["$entry"]["4"]["count"], 1); + юТест.ПроверитьРавенство(Данные["$entry"]["5"]["count"], 1); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьРаботуЗамераВремени() Экспорт + + ТекстСкрипта = "Sleep(1000);"; + + ИмяФайлаВывода = ПолучитьВыводДляСкрипта(ТекстСкрипта); + Ч = Новый ЧтениеJson(); + Ч.ОткрытьФайл(ИмяФайлаВывода); + + Данные = ПолучитьДанныеПервогоФайла(ПрочитатьЗначение(Ч)); + юТест.ПроверитьБольшеИлиРавно(Данные["$entry"]["1"]["time"], 1000); + +КонецПроцедуры + +Функция ПутьОСкрипт() + Возврат ОбъединитьПути(КаталогПрограммы(), "oscript.exe"); +КонецФункции + +Функция НормализоватьПереводыСтрок(Знач ИсходнаяСтрока) + Возврат СтрЗаменить(ИсходнаяСтрока, Символы.ВК, ""); +КонецФункции + From c9eefb03e5df15f8755c654b100391b209daa850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D1=A3=D0=B9=20=D0=91=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Wed, 14 Dec 2016 14:44:24 +0300 Subject: [PATCH 18/63] =?UTF-8?q?CodeStat:=20=D0=BF=D0=BE=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=82=D0=B5=D1=81=D1=82.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/codestat.os | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/tests/codestat.os b/tests/codestat.os index 72771e8fa..ee55e7c7d 100644 --- a/tests/codestat.os +++ b/tests/codestat.os @@ -41,8 +41,17 @@ ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаОСкрипта); ЗаписьТекста.Записать(ТекстСкрипта); ЗаписьТекста.Закрыть(); + + ИмяФайлаВывода = ЗапуститьФайлСкрипта(ИмяФайлаОСкрипта); + Чтение = Новый ЧтениеJson(); + Чтение.ОткрытьФайл(ИмяФайлаВывода); + + Результат = ПрочитатьЗначение(Чтение); + Чтение.Закрыть(); + + УдалитьФайлы(ИмяФайлаВывода); - Возврат ЗапуститьФайлСкрипта(ИмяФайлаОСкрипта); + Возврат Результат; КонецФункции @@ -94,7 +103,7 @@ Функция ПрочитатьЗначение(Знач Чтение) Если Не Чтение.Прочитать() Тогда - Возврат Неопределено; + ВызватьИсключение "Неверный JSON"; КонецЕсли; Если Чтение.ТипТекущегоЗначения = ТипЗначенияJson.НачалоОбъекта Тогда @@ -169,11 +178,9 @@ |" ; - ИмяФайлаВывода = ПолучитьВыводДляСкрипта(ТекстСкрипта); - Ч = Новый ЧтениеJson(); - Ч.ОткрытьФайл(ИмяФайлаВывода); + Данные = ПолучитьВыводДляСкрипта(ТекстСкрипта); + Данные = ПолучитьДанныеПервогоФайла(Данные); - Данные = ПолучитьДанныеПервогоФайла(ПрочитатьЗначение(Ч)); юТест.ПроверитьРавенство(Данные["$entry"]["1"]["count"], 1); юТест.ПроверитьРавенство(Данные["$entry"]["2"]["count"], 1); юТест.ПроверитьРавенство(Данные["$entry"]["3"]["count"], 0); @@ -194,11 +201,9 @@ |" ; - ИмяФайлаВывода = ПолучитьВыводДляСкрипта(ТекстСкрипта); - Ч = Новый ЧтениеJson(); - Ч.ОткрытьФайл(ИмяФайлаВывода); + Данные = ПолучитьВыводДляСкрипта(ТекстСкрипта); + Данные = ПолучитьДанныеПервогоФайла(Данные); - Данные = ПолучитьДанныеПервогоФайла(ПрочитатьЗначение(Ч)); юТест.ПроверитьРавенство(Данные["$entry"]["1"]["count"], 1); юТест.ПроверитьРавенство(Данные["$entry"]["2"]["count"], 0); юТест.ПроверитьРавенство(Данные["$entry"]["3"]["count"], 1); @@ -211,11 +216,9 @@ ТекстСкрипта = "Sleep(1000);"; - ИмяФайлаВывода = ПолучитьВыводДляСкрипта(ТекстСкрипта); - Ч = Новый ЧтениеJson(); - Ч.ОткрытьФайл(ИмяФайлаВывода); + Данные = ПолучитьВыводДляСкрипта(ТекстСкрипта); + Данные = ПолучитьДанныеПервогоФайла(Данные); - Данные = ПолучитьДанныеПервогоФайла(ПрочитатьЗначение(Ч)); юТест.ПроверитьБольшеИлиРавно(Данные["$entry"]["1"]["time"], 1000); КонецПроцедуры From 15bf727bc6ee46aed9af69e3912fa298332563cc Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Wed, 14 Dec 2016 17:14:13 +0300 Subject: [PATCH 19/63] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=82=D0=B8=D0=BF=D0=BE=D0=B2=D1=8B=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=B0=D0=BA=D0=B5=D1=82=D1=8B=20=D0=B2=20=D0=BD=D0=BE=D1=87?= =?UTF-8?q?=D0=BD=D0=BE=D0=B9=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oscript-library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscript-library b/oscript-library index 7a302bf7c..900a5a8e3 160000 --- a/oscript-library +++ b/oscript-library @@ -1 +1 @@ -Subproject commit 7a302bf7cdf6633574a30b17057c844b224b8de5 +Subproject commit 900a5a8e3e1c8467fe07bd2efd8f74bcbf5b94fe From 4f0f70e4260284c03cbb1d5a6da9bfcc3e9e964a Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 16 Dec 2016 15:55:33 +0300 Subject: [PATCH 20/63] =?UTF-8?q?CodeStat:=20=D0=A3=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=BE=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=82=D0=B5=D1=81=D1=82=D0=BE=D0=B2?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/codestat.os | 157 +++++++++++++++++++++++++++---------- tests/codestat/if_endif.os | 11 +++ tests/codestat/sub_path.os | 3 + 3 files changed, 129 insertions(+), 42 deletions(-) create mode 100644 tests/codestat/if_endif.os create mode 100644 tests/codestat/sub_path.os diff --git a/tests/codestat.os b/tests/codestat.os index ee55e7c7d..b86557d82 100644 --- a/tests/codestat.os +++ b/tests/codestat.os @@ -1,4 +1,4 @@ -Перем юТест; +Перем юТест; Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт @@ -7,9 +7,8 @@ ВсеТесты = Новый Массив; ВсеТесты.Добавить("ТестДолжен_ПолучитьПутьКOscript"); - ВсеТесты.Добавить("ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиИстинаКонецЕсли"); - ВсеТесты.Добавить("ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиЛожьИначеКонецЕсли"); ВсеТесты.Добавить("ТестДолжен_ПроверитьРаботуЗамераВремени"); + ВсеТесты.Добавить("ТестДолжен_ВызватьТестыИзФайлов"); Возврат ВсеТесты; @@ -34,7 +33,7 @@ КонецФункции -Функция ПолучитьВыводДляСкрипта(Знач ТекстСкрипта) +Функция ПолучитьВыводДляТекста(Знач ТекстСкрипта) ИмяФайлаОСкрипта = ПолучитьИмяВременногоФайла("os"); @@ -42,7 +41,18 @@ ЗаписьТекста.Записать(ТекстСкрипта); ЗаписьТекста.Закрыть(); + Результат = ПолучитьВыводДляСкрипта(ИмяФайлаОСкрипта); + + УдалитьФайлы(ИмяФайлаОСкрипта); + + Возврат Результат; + +КонецФункции + +Функция ПолучитьВыводДляСкрипта(Знач ИмяФайлаОСкрипта) + ИмяФайлаВывода = ЗапуститьФайлСкрипта(ИмяФайлаОСкрипта); + Чтение = Новый ЧтениеJson(); Чтение.ОткрытьФайл(ИмяФайлаВывода); @@ -58,7 +68,7 @@ Функция ЗапуститьФайлСкрипта(Знач ИмяФайлаОСкрипта) Перем ИмяФайла, СтрокаЗапуска; - ИмяФайлаВывода = ПолучитьИмяВременногоФайла("txt"); + ИмяФайлаВывода = ПолучитьИмяВременногоФайла("json"); Путь = СтрокаЗапускаОСкрипта(ПутьОСкрипт()); @@ -69,7 +79,7 @@ ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаСистемногоСкриптаЗапуска, КодировкаТекста.Oem); ЗаписьТекста.ЗаписатьСтроку("@echo off"); - ЗаписьТекста.ЗаписатьСтроку(Путь + " -codestat=" + ИмяФайлаВывода + " " + ИмяФайлаОСкрипта + " > nul"); + ЗаписьТекста.ЗаписатьСтроку(Путь + " -codestat=" + ИмяФайлаВывода + " " + ИмяФайлаОСкрипта); ЗаписьТекста.Закрыть(); СтрокаЗапуска = ИмяФайлаСистемногоСкриптаЗапуска; @@ -95,6 +105,8 @@ Процесс.Запустить(); Процесс.ОжидатьЗавершения(); + + УдалитьФайлы(ИмяФайлаСистемногоСкриптаЗапуска); Возврат ИмяФайлаВывода; @@ -167,56 +179,118 @@ КонецФункции -Процедура ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиИстинаКонецЕсли() Экспорт +Функция ПолучитьОжидаемуюСтатистику(Знач ТекстСкрипта) - ТекстСкрипта = - "Если Истина Тогда // 1: 1 - | Ф = 1; // 2: 1 - |Иначе // 3: 0 - | Ф = 2; // 4: 0 - |КонецЕсли; // 5: 1 - |" - ; + Разделитель = "//-"; - Данные = ПолучитьВыводДляСкрипта(ТекстСкрипта); - Данные = ПолучитьДанныеПервогоФайла(Данные); + ТаблицаРезультата = Новый ТаблицаЗначений; + ТаблицаРезультата.Колонки.Добавить("ИмяМетода"); + ТаблицаРезультата.Колонки.Добавить("НомерСтроки"); + ТаблицаРезультата.Колонки.Добавить("Количество"); + + ПолныйТекст = Новый ТекстовыйДокумент; + ПолныйТекст.УстановитьТекст(ТекстСкрипта); + + Для НомерСтроки = 1 По ПолныйТекст.КоличествоСтрок() Цикл + + ТекстСтроки = ПолныйТекст.ПолучитьСтроку(НомерСтроки); + ПоложениеКлюча = СтрНайти(ТекстСтроки, Разделитель); + + Если ПоложениеКлюча = 0 Тогда + Продолжить; + КонецЕсли; + + СтрокаОжидаемогоРезультата = СокрЛП(Сред(ТекстСтроки, ПоложениеКлюча + СтрДлина(Разделитель))); + ОжидаемыеДанные = СтрРазделить(СтрокаОжидаемогоРезультата, ":"); + Если ОжидаемыеДанные.Количество() < 2 Тогда + Продолжить; + КонецЕсли; + + НоваяСтрока = ТаблицаРезультата.Добавить(); + НоваяСтрока.ИмяМетода = ОжидаемыеДанные[0]; + НоваяСтрока.НомерСтроки = НомерСтроки; + НоваяСтрока.Количество = Число(СокрЛП(ОжидаемыеДанные[1])); + + КонецЦикла; + + Возврат ТаблицаРезультата; + +КонецФункции + +Процедура ВыполнитьСравнениеСтатистики(Знач ПолученнаяСтатистика, Знач ОжидаемаяСтатистика, Знач ИмяТеста) + + // Из json-а получаем соответствие, но сравнивать удобнее таблицами + + ТаблицаПолученнойСтатистики = ОжидаемаяСтатистика.Скопировать(); + ТаблицаПолученнойСтатистики.Колонки.Добавить("КоличествоПолучено"); + + Для Каждого мМетод Из ПолученнаяСтатистика Цикл + + Если Не ТипЗнч(мМетод.Значение) = Тип("Соответствие") Тогда + Продолжить; + КонецЕсли; + + Для Каждого мДанныеМетода Из мМетод.Значение Цикл + + НоваяСтрока = ТаблицаПолученнойСтатистики.Добавить(); + НоваяСтрока.ИмяМетода = мМетод.Ключ; + НоваяСтрока.НомерСтроки = Число(мДанныеМетода.Ключ); + НоваяСтрока.Количество = -мДанныеМетода.Значение["count"]; + НоваяСтрока.КоличествоПолучено = мДанныеМетода.Значение["count"]; + + КонецЦикла; + + КонецЦикла; + + ТаблицаПолученнойСтатистики.Свернуть("ИмяМетода, НомерСтроки", "Количество, КоличествоПолучено"); + + Для Каждого мСтрокаПроверки Из ТаблицаПолученнойСтатистики Цикл + + Получили = мСтрокаПроверки.КоличествоПолучено; + Ожидали = мСтрокаПроверки.Количество + мСтрокаПроверки.КоличествоПолучено; + ТекстОшибкиСравнения = СтрШаблон("%1: Сравнение для %2, строка %3", + ИмяТеста, мСтрокаПроверки.ИмяМетода, мСтрокаПроверки.НомерСтроки + ); + + юТест.ПроверитьРавенство(Получили, Ожидали, ТекстОшибкиСравнения); + + КонецЦикла; - юТест.ПроверитьРавенство(Данные["$entry"]["1"]["count"], 1); - юТест.ПроверитьРавенство(Данные["$entry"]["2"]["count"], 1); - юТест.ПроверитьРавенство(Данные["$entry"]["3"]["count"], 0); - юТест.ПроверитьРавенство(Данные["$entry"]["4"]["count"], 0); - юТест.ПроверитьРавенство(Данные["$entry"]["5"]["count"], 1); - КонецПроцедуры +Процедура ТестДолжен_ВызватьТестыИзФайлов() Экспорт -Процедура ТестДолжен_ПроверитьСтатистикуУсловия_ЕслиЛожьИначеКонецЕсли() Экспорт + Файлы = НайтиФайлы("codestat", "*.os"); + Для Каждого мФайл Из Файлы Цикл - ТекстСкрипта = - "Если Ложь Тогда // 1: 1 - | Ф = 1; // 2: 0 - |Иначе // 3: 1 - | Ф = 2; // 4: 1 - |КонецЕсли; // 5: 1 - |" - ; + Попытка - Данные = ПолучитьВыводДляСкрипта(ТекстСкрипта); - Данные = ПолучитьДанныеПервогоФайла(Данные); + Чтение = Новый ЧтениеТекста; + Чтение.Открыть(мФайл.ПолноеИмя); + ТекстСкрипта = Чтение.Прочитать(); + + Данные = ПолучитьВыводДляСкрипта(мФайл.ПолноеИмя); + Данные = ПолучитьДанныеПервогоФайла(Данные); + + ОжидаемыеДанные = ПолучитьОжидаемуюСтатистику(ТекстСкрипта); + ВыполнитьСравнениеСтатистики(Данные, ОжидаемыеДанные, мФайл.ИмяБезРасширения); + + Исключение + + Сообщить(мФайл.ПолноеИмя, СтатусСообщения.Важное); + ВызватьИсключение; + + КонецПопытки; + + КонецЦикла; - юТест.ПроверитьРавенство(Данные["$entry"]["1"]["count"], 1); - юТест.ПроверитьРавенство(Данные["$entry"]["2"]["count"], 0); - юТест.ПроверитьРавенство(Данные["$entry"]["3"]["count"], 1); - юТест.ПроверитьРавенство(Данные["$entry"]["4"]["count"], 1); - юТест.ПроверитьРавенство(Данные["$entry"]["5"]["count"], 1); - КонецПроцедуры Процедура ТестДолжен_ПроверитьРаботуЗамераВремени() Экспорт ТекстСкрипта = "Sleep(1000);"; - Данные = ПолучитьВыводДляСкрипта(ТекстСкрипта); + Данные = ПолучитьВыводДляТекста(ТекстСкрипта); Данные = ПолучитьДанныеПервогоФайла(Данные); юТест.ПроверитьБольшеИлиРавно(Данные["$entry"]["1"]["time"], 1000); @@ -230,4 +304,3 @@ Функция НормализоватьПереводыСтрок(Знач ИсходнаяСтрока) Возврат СтрЗаменить(ИсходнаяСтрока, Символы.ВК, ""); КонецФункции - diff --git a/tests/codestat/if_endif.os b/tests/codestat/if_endif.os new file mode 100644 index 000000000..e99b4c42f --- /dev/null +++ b/tests/codestat/if_endif.os @@ -0,0 +1,11 @@ +Если Истина Тогда //- $entry: 1 + Ф = 1; //- $entry: 1 +Иначе //- $entry: 0 + Ф = 2; //- $entry: 0 +КонецЕсли; //- $entry: 1 + +Если Ложь Тогда //- $entry: 1 + Ф = 1; //- $entry: 0 +Иначе //- $entry: 1 + Ф = 2; //- $entry: 1 +КонецЕсли; //- $entry: 1 diff --git a/tests/codestat/sub_path.os b/tests/codestat/sub_path.os new file mode 100644 index 000000000..66f6c0e0b --- /dev/null +++ b/tests/codestat/sub_path.os @@ -0,0 +1,3 @@ +Процедура path() //- path: 1 +КонецПроцедуры //- path: 1 +path(); //- $entry: 1 \ No newline at end of file From 38acd4c1d461479aa2c69367ced19e3141cad57f Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 16 Dec 2016 15:58:36 +0300 Subject: [PATCH 21/63] =?UTF-8?q?CodeStat:=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D1=84=D0=BE=D1=80=D0=BC=D0=B0?= =?UTF-8?q?=D1=82=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Свойство, содержащее путь к файлу теперь называется `#path`, чтобы избежать неверного вывода в случае, если модуль содержит метод `path()`. --- src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs index e5b4a3bbc..5745e0f41 100644 --- a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs @@ -72,7 +72,7 @@ public void OutputCodeStat() jwriter.WritePropertyName(source.Key, true); jwriter.WriteStartObject(); - jwriter.WritePropertyName("path"); + jwriter.WritePropertyName("#path"); jwriter.WriteValue(source.Key); foreach (var method in source.GroupBy((arg) => arg.Key.SubName)) { From c9ca2ed59d431bb391cf5a1b72c5a4221dff8849 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Sun, 18 Dec 2016 16:03:14 +0300 Subject: [PATCH 22/63] =?UTF-8?q?CodeStat:=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/codestat/try.os | 11 +++++++++++ tests/codestat/while.os | 9 +++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/codestat/try.os create mode 100644 tests/codestat/while.os diff --git a/tests/codestat/try.os b/tests/codestat/try.os new file mode 100644 index 000000000..7f65788f2 --- /dev/null +++ b/tests/codestat/try.os @@ -0,0 +1,11 @@ +Попытка //- $entry: 1 + А = 0; //- $entry: 1 +Исключение //- $entry: 0 + Б = 0; //- $entry: 0 +КонецПопытки; //- $entry: 1 + +Попытка //- $entry: 1 + А = Число("ы"); //- $entry: 1 +Исключение //- $entry: 1 + Б = 0; //- $entry: 1 +КонецПопытки; //- $entry: 1 diff --git a/tests/codestat/while.os b/tests/codestat/while.os new file mode 100644 index 000000000..53476a859 --- /dev/null +++ b/tests/codestat/while.os @@ -0,0 +1,9 @@ +Пока Истина Цикл //- $entry: 1 + А = 0; //- $entry: 1 + Прервать; //- $entry: 1 + Б = 0; //- $entry: 0 +КонецЦикла; //- $entry: 0 + +Для сч = 1 По 2 Цикл //- $entry: 3 + А = 0; //- $entry: 2 +КонецЦикла; //- $entry: 2 From d0fcf00f0f6227aa4fc7eb8a122adbab2519b4ae Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Sun, 18 Dec 2016 16:03:32 +0300 Subject: [PATCH 23/63] =?UTF-8?q?CodeStat:=20=D0=98=D1=81=D0=BF=D1=80?= =?UTF-8?q?=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BF=D0=BE=D1=81=D1=87=D1=91?= =?UTF-8?q?=D1=82=20=D1=86=D0=B8=D0=BA=D0=BB=D0=B0=20=D0=9F=D0=BE=D0=BA?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine/Compiler/Compiler.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index 55ee5a00b..4a7bb1bee 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -829,7 +829,6 @@ private void BuildWhileStatement() { NextToken(); var conditionIndex = _module.Code.Count; - AddCommand(OperationCode.LineNum, _parser.CurrentLine); var loopRecord = NestedLoopInfo.New(); loopRecord.startPoint = conditionIndex; _nestedLoops.Push(loopRecord); From 0b57fb72fb224fd307d90d8b4913ddd24e350a19 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 23 Dec 2016 13:41:52 +0300 Subject: [PATCH 24/63] =?UTF-8?q?CodeStat:=20=D0=A3=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D0=B0=D0=BD=D0=B0=20=D0=BA=D0=BE=D0=B4=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20JSON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/codestat.os | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codestat.os b/tests/codestat.os index b86557d82..4de6ef42f 100644 --- a/tests/codestat.os +++ b/tests/codestat.os @@ -54,7 +54,7 @@ ИмяФайлаВывода = ЗапуститьФайлСкрипта(ИмяФайлаОСкрипта); Чтение = Новый ЧтениеJson(); - Чтение.ОткрытьФайл(ИмяФайлаВывода); + Чтение.ОткрытьФайл(ИмяФайлаВывода, "UTF-8"); Результат = ПрочитатьЗначение(Чтение); Чтение.Закрыть(); From 947ad18fe8f917baa8f6d5e1a2f0d17b1ac77145 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 23 Dec 2016 13:46:01 +0300 Subject: [PATCH 25/63] =?UTF-8?q?CodeStat:=20=D1=83=D0=B1=D1=80=D0=B0?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BD=D0=B0=D0=BA=D1=80=D1=83=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B2=D0=BD=D1=83=D1=82=D1=80=D0=B8=20=D0=BE=D0=B4=D0=BD?= =?UTF-8?q?=D0=BE=D0=B9=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Если оп-код `LineNum` устанавливает тот же самый номер строки, то увеличения счётчика проходов теперь не происходит. --- src/ScriptEngine/Machine/MachineInstance.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index 341ce299a..8ae8d5502 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -409,10 +409,6 @@ private void MainCommandLoop() { var command = _module.Code[_currentFrame.InstructionPointer]; _commands[(int)command.Code](command.Argument); - - if (command.Code == OperationCode.LineNum) - CodeStat_LineReached(); - } } catch (RuntimeException) @@ -1372,7 +1368,11 @@ private void RaiseException(int arg) private void LineNum(int arg) { - _currentFrame.LineNumber = arg; + if (_currentFrame.LineNumber != arg) + { + _currentFrame.LineNumber = arg; + CodeStat_LineReached(); + } NextInstruction(); } From cd83d1d85df6c2572775b8b250aa47d869a28a6f Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 23 Dec 2016 14:10:28 +0300 Subject: [PATCH 26/63] =?UTF-8?q?CodeStat:=20=D0=B4=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=82=D0=B5=D1=81=D1=82=D1=8B?= =?UTF-8?q?=20foreach=20=D0=B8=20subs.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/codestat/foreach.os | 13 +++++++++++++ tests/codestat/subs.os | 16 ++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/codestat/foreach.os create mode 100644 tests/codestat/subs.os diff --git a/tests/codestat/foreach.os b/tests/codestat/foreach.os new file mode 100644 index 000000000..e75d1329f --- /dev/null +++ b/tests/codestat/foreach.os @@ -0,0 +1,13 @@ +ТестовыйМассив = Новый Массив; //- $entry: 1 +ТестовыйМассив.Добавить(1); //- $entry: 1 +ТестовыйМассив.Добавить(2); //- $entry: 1 +ТестовыйМассив.Добавить(3); //- $entry: 1 +ТестовыйМассив.Добавить(4); //- $entry: 1 + +Для Каждого мЗначение Из ТестовыйМассив Цикл //- $entry: 3 + + Если мЗначение = 3 Тогда //- $entry: 3 + Прервать; //- $entry: 1 + КонецЕсли; //- $entry: 2 + +КонецЦикла; //- $entry: 2 diff --git a/tests/codestat/subs.os b/tests/codestat/subs.os new file mode 100644 index 000000000..7f80c7155 --- /dev/null +++ b/tests/codestat/subs.os @@ -0,0 +1,16 @@ +Функция Фибоначчи(Знач Число) //- Фибоначчи: 15 + + Если Число < 2 Тогда //- Фибоначчи: 15 + Возврат 1; //- Фибоначчи: 8 + КонецЕсли; //- Фибоначчи: 7 + + Возврат Фибоначчи(Число - 1) //- Фибоначчи: 7 + // Многострочные вычисления распознавать не умеем + // Всё падает на первую строку + + Фибоначчи(Число - 2) //- Фибоначчи: 0 + ; + +КонецФункции //- Фибоначчи: 15 + +Ф = Фибоначчи(5); //- $entry: 1 +// \ No newline at end of file From f55e476d0d4edaf9040b6ba39ba76670fd1f2ea7 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Fri, 23 Dec 2016 15:26:07 +0300 Subject: [PATCH 27/63] =?UTF-8?q?CodeStat:=20=D0=9F=D0=BE=D0=B4=D1=81?= =?UTF-8?q?=D1=87=D1=91=D1=82=20=D0=B2=D1=8B=D0=B7=D0=BE=D0=B2=D0=B0=20?= =?UTF-8?q?=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Вызов функции в многострочном выражении подсчитывается независимо от корневого выражения. --- src/ScriptEngine/Compiler/Compiler.cs | 21 +++++++++++---------- src/ScriptEngine/CompilerService.cs | 3 +++ src/ScriptEngine/ScriptingEngine.cs | 4 ++++ tests/codestat/subs.os | 4 +++- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index 4a7bb1bee..72de460c0 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -61,6 +61,8 @@ public Compiler() } + public bool ProduceExtraCode { get; set; } + public ModuleImage Compile(Parser parser, ICompilerContext context) { _module = new ModuleImage(); @@ -1257,6 +1259,7 @@ private void BuildPrimaryNode() private void ProcessPrimaryIdentifier() { var identifier = _lastExtractedLexem.Content; + var lineNumber = _lastExtractedLexem.LineNumber; NextToken(); if (IsContinuationToken(ref _lastExtractedLexem)) { @@ -1265,7 +1268,7 @@ private void ProcessPrimaryIdentifier() } else if (_lastExtractedLexem.Token == Token.OpenPar) { - BuildFunctionCall(identifier); + BuildFunctionCall(identifier, lineNumber); BuildContinuationRightHand(); } else @@ -1497,15 +1500,10 @@ private void BuildIndexedAccess(string identifier) AddCommand(OperationCode.PushIndexed, 0); } - private void BuildProcedureCall(string identifier) - { - var args = PushMethodArgumentsBeforeCall(); - BuildMethodCall(identifier, args, false); - } - - private void BuildFunctionCall(string identifier) + private void BuildFunctionCall(string identifier, int callLineNumber) { bool[] args = PushMethodArgumentsBeforeCall(); + AddCommand(OperationCode.LineNum, callLineNumber, isExtraCode: true); BuildMethodCall(identifier, args, true); } @@ -1533,7 +1531,7 @@ private void BuildMethodCall(string identifier, bool[] argsPassed, bool asFuncti } CheckFactArguments(methInfo, argsPassed); } - + if(asFunction) AddCommand(OperationCode.CallFunc, GetMethodRefNumber(ref methBinding)); else @@ -1789,8 +1787,11 @@ private Token[] PopStructureToken() return tok; } - private int AddCommand(OperationCode code, int arg) + private int AddCommand(OperationCode code, int arg, bool isExtraCode = false) { + if (isExtraCode && !ProduceExtraCode) + return -1; + var addr = _module.Code.Count; _module.Code.Add(new Command() { Code = code, Argument = arg }); return addr; diff --git a/src/ScriptEngine/CompilerService.cs b/src/ScriptEngine/CompilerService.cs index d393cc8e8..0c212f066 100644 --- a/src/ScriptEngine/CompilerService.cs +++ b/src/ScriptEngine/CompilerService.cs @@ -27,6 +27,8 @@ internal CompilerService(CompilerContext outerContext) _currentContext = new ModuleCompilerContext(outerContext); } + public bool ProduceExtraCode { get; set; } + public int DefineVariable(string name, SymbolType type) { RegisterScopeIfNeeded(); @@ -87,6 +89,7 @@ private ScriptModuleHandle Compile(ICodeSource source) parser.Code = source.Code; var compiler = new Compiler.Compiler(); + compiler.ProduceExtraCode = ProduceExtraCode; compiler.DirectiveHandler = ResolveDirective; if (DirectiveResolver != null) diff --git a/src/ScriptEngine/ScriptingEngine.cs b/src/ScriptEngine/ScriptingEngine.cs index 62e670942..7f810395b 100644 --- a/src/ScriptEngine/ScriptingEngine.cs +++ b/src/ScriptEngine/ScriptingEngine.cs @@ -27,6 +27,8 @@ public ScriptingEngine() _scriptFactory = new ScriptSourceFactory(); } + public bool ProduceExtraCode { get; set; } + public void AttachAssembly(System.Reflection.Assembly asm) { ContextDiscoverer.DiscoverClasses(asm); @@ -79,6 +81,7 @@ public ICodeSourceFactory Loader public CompilerService GetCompilerService() { var cs = new CompilerService(Environment.SymbolsContext); + cs.ProduceExtraCode = ProduceExtraCode; cs.DirectiveResolver = DirectiveResolver; return cs; } @@ -144,6 +147,7 @@ public AttachedScriptsFactory AttachedScriptsFactory public void SetCodeStatisticsCollector(ICodeStatCollector collector) { + ProduceExtraCode = true; _machine.SetCodeStatisticsCollector(collector); } diff --git a/tests/codestat/subs.os b/tests/codestat/subs.os index 7f80c7155..5c3d66469 100644 --- a/tests/codestat/subs.os +++ b/tests/codestat/subs.os @@ -7,7 +7,9 @@ Возврат Фибоначчи(Число - 1) //- Фибоначчи: 7 // Многострочные вычисления распознавать не умеем // Всё падает на первую строку - + Фибоначчи(Число - 2) //- Фибоначчи: 0 + + Фибоначчи(Число - 2) //- Фибоначчи: 7 + + Число("1") //- Фибоначчи: 0 + - Число("1") //- Фибоначчи: 0 ; КонецФункции //- Фибоначчи: 15 From 1d6a7efbbb87c6128c51e391c7707ed494665108 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Tue, 27 Dec 2016 17:43:44 +0300 Subject: [PATCH 28/63] =?UTF-8?q?=D0=9E=D1=81=D0=B2=D0=B5=D0=B6=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8=D0=BE=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oscript-library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscript-library b/oscript-library index 900a5a8e3..06fb21aea 160000 --- a/oscript-library +++ b/oscript-library @@ -1 +1 @@ -Subproject commit 900a5a8e3e1c8467fe07bd2efd8f74bcbf5b94fe +Subproject commit 06fb21aea24bbfedb238c9e23306121e8b441462 From 7483a75593ef8e568051246eca62824db0fb8fbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D1=A3=D0=B9=20=D0=91=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Tue, 3 Jan 2017 22:30:53 +0300 Subject: [PATCH 29/63] =?UTF-8?q?XML:=20=D0=92=D0=BE=D0=BF=D0=BB=D0=BE?= =?UTF-8?q?=D1=89=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=B2=D0=BE=D0=B9=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D0=B0=20`=D0=9A=D0=BE=D0=BD=D1=82=D0=B5=D0=BA?= =?UTF-8?q?=D1=81=D1=82=D0=9F=D1=80=D0=BE=D1=81=D1=82=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=D1=81=D1=82=D0=B2=D0=98=D0=BC=D0=B5=D0=BD`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/Xml/XmlNamespaceContext.cs | 99 +++++++++++++++++++ .../Library/Xml/XmlReaderImpl.cs | 18 +++- .../Library/Xml/XmlWriterImpl.cs | 23 ++++- .../ScriptEngine.HostedScript.csproj | 1 + tests/xmlread.os | 69 ++++++++++++- tests/xmlwrite.os | 36 +++++++ 6 files changed, 241 insertions(+), 5 deletions(-) create mode 100644 src/ScriptEngine.HostedScript/Library/Xml/XmlNamespaceContext.cs diff --git a/src/ScriptEngine.HostedScript/Library/Xml/XmlNamespaceContext.cs b/src/ScriptEngine.HostedScript/Library/Xml/XmlNamespaceContext.cs new file mode 100644 index 000000000..60572616f --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/Xml/XmlNamespaceContext.cs @@ -0,0 +1,99 @@ +/*---------------------------------------------------------- +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 ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; + +namespace ScriptEngine.HostedScript.Library.Xml +{ + [ContextClass("КонтекстПространствИменXML", "XMLNamespaceContext")] + public class XmlNamespaceContext : AutoContext + { + readonly IDictionary _nsmap; + + public XmlNamespaceContext(int depth, IDictionary map) + { + Depth = depth; + _nsmap = map; + } + + [ContextProperty("Глубина", "Depth")] + public int Depth { get; } + + [ContextProperty("ПространствоИменПоУмолчанию", "DefaultNamespace")] + public string DefaultNamespace + { + get + { + if (_nsmap.ContainsKey("")) + return _nsmap[""]; + return ""; + } + } + + [ContextMethod("URIПространствИмен", "NamespaceURIs")] + public ArrayImpl NamespaceUris() + { + var result = ArrayImpl.Constructor() as ArrayImpl; + foreach (var ns in _nsmap.Values.Distinct()) + { + result.Add(ValueFactory.Create(ns)); + } + return result; + } + + [ContextMethod("НайтиURIПространстваИмен", "LookupNamespaceURI")] + public IValue LookupNamespaceUri(string prefix) + { + if (_nsmap.ContainsKey(prefix)) + return ValueFactory.Create(_nsmap[prefix]); + return ValueFactory.Create(); + } + + [ContextMethod("НайтиПрефикс", "LookupPrefix")] + public IValue LookupPrefix(string namespaceUri) + { + foreach (var kv in _nsmap) + { + if (kv.Value.Equals(namespaceUri, StringComparison.Ordinal)) + return ValueFactory.Create(kv.Key); + } + return ValueFactory.Create(); + } + + [ContextMethod("Префиксы", "Prefixes")] + public ArrayImpl Prefixes(string namespaceUri) + { + var result = ArrayImpl.Constructor() as ArrayImpl; + foreach (var prefix in _nsmap + .Where((arg) => arg.Value.Equals(namespaceUri, StringComparison.Ordinal)) + .Select((arg) => arg.Key)) + { + result.Add(ValueFactory.Create(prefix)); + } + + return result; + } + + [ContextMethod("СоответствияПространствИмен", "NamespaceMappings")] + public MapImpl NamespaceMappings() + { + var result = MapImpl.Constructor() as MapImpl; + foreach (var data in _nsmap) + { + result.Insert(ValueFactory.Create(data.Key), ValueFactory.Create(data.Value)); + } + + return result; + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/Xml/XmlReaderImpl.cs b/src/ScriptEngine.HostedScript/Library/Xml/XmlReaderImpl.cs index 245d62a5f..2457bd337 100644 --- a/src/ScriptEngine.HostedScript/Library/Xml/XmlReaderImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/Xml/XmlReaderImpl.cs @@ -166,12 +166,26 @@ public string InputEncoding } } + private int Depth + { + get + { + if (_reader.NodeType == XmlNodeType.EndElement) + return _reader.Depth; + + if (_emptyElemReadState == EmptyElemCompabilityState.EmptyElementRead) + return _reader.Depth; + + return _reader.Depth + 1; + } + } + [ContextProperty("КонтекстПространствИмен", "NamespaceContext")] - public object NamespaceContext + public XmlNamespaceContext NamespaceContext { get { - throw new NotSupportedException(); + return new XmlNamespaceContext(Depth, _reader.GetNamespacesInScope(XmlNamespaceScope.All)); } } diff --git a/src/ScriptEngine.HostedScript/Library/Xml/XmlWriterImpl.cs b/src/ScriptEngine.HostedScript/Library/Xml/XmlWriterImpl.cs index 59f429a5a..85437f00a 100644 --- a/src/ScriptEngine.HostedScript/Library/Xml/XmlWriterImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/Xml/XmlWriterImpl.cs @@ -20,11 +20,27 @@ public class XmlWriterImpl : AutoContext, IDisposable { private XmlTextWriter _writer; private StringWriter _stringWriter; + private int _depth; + private Stack> _nsmap = new Stack>(); private const int INDENT_SIZE = 4; public XmlWriterImpl() { + _nsmap.Push(new Dictionary()); + } + + private void EnterScope() + { + ++_depth; + var newMap = _nsmap.Peek().ToDictionary((kv) => kv.Key, (kv) => kv.Value); + _nsmap.Push(newMap); + } + + private void ExitScope() + { + _nsmap.Pop(); + --_depth; } #region Properties @@ -50,11 +66,11 @@ public bool Indent } [ContextProperty("КонтекстПространствИмен", "NamespaceContext")] - public object NamespaceContext + public XmlNamespaceContext NamespaceContext { get { - throw new NotImplementedException(); + return new XmlNamespaceContext(_depth, _nsmap.Peek()); } } @@ -112,6 +128,7 @@ public void WriteEndAttribute() public void WriteEndElement() { _writer.WriteEndElement(); + ExitScope(); } [ContextMethod("ЗаписатьНачалоАтрибута","WriteStartAttribute")] @@ -139,6 +156,7 @@ public void WriteStartElement(string name, string ns = null) { _writer.WriteStartElement(name, ns); } + EnterScope(); } [ContextMethod("ЗаписатьОбъявлениеXML","WriteXMLDeclaration")] @@ -157,6 +175,7 @@ public void WriteCDATASection(string data) public void WriteNamespaceMapping(string prefix, string uri) { _writer.WriteAttributeString("xmlns", prefix, null, uri); + _nsmap.Peek()[prefix] = uri; } [ContextMethod("ЗаписатьСсылкуНаСущность","WriteEntityReference")] diff --git a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj index 420ffbed4..7aa3dd377 100644 --- a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj +++ b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj @@ -199,6 +199,7 @@ + diff --git a/tests/xmlread.os b/tests/xmlread.os index c2f165809..21146f2da 100644 --- a/tests/xmlread.os +++ b/tests/xmlread.os @@ -26,6 +26,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтениеНепустыхЭлементовСАтрибутами"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтениеПустыхЭлементовCЗаголовкомXML"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоПропускПереходитНаКонецЭлемента"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьРаботуКонтекстаПространствИмен"); Возврат ВсеТесты; КонецФункции @@ -190,4 +191,70 @@ Возврат Текст; -КонецФункции \ No newline at end of file +КонецФункции + +Процедура ТестДолжен_ПроверитьРаботуКонтекстаПространствИмен() Экспорт + + СтрокаСПространствами = + " + | + | + | + | + |"; + + Чтение = Новый ЧтениеXML; + Чтение.УстановитьСтроку(СтрокаСПространствами); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 1, "root:start"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns1"), Неопределено, "Пространства в root"); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns2"), Неопределено, "Пространства в root"); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 2, "child2:start"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns1"), Неопределено, "Пространства в child2:start"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns2"), Неопределено, "Пространства в child2:start"); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 3, "child3:start"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns1"), Неопределено, "Пространства в child3:start"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns2"), Неопределено, "Пространства в child3:start"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns3"), Неопределено, "Пространства в child3:start"); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 2, "child3:end"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns1"), Неопределено, "Пространства в child3:end"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns2"), Неопределено, "Пространства в child3:end"); + + // TODO: Несовместимость поведения чтения XML в .NET (*1) + // юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns3"), Неопределено, "Пространства в child3:end"); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 3, "child4:start"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns1"), Неопределено); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns2"), Неопределено); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns3"), Неопределено); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns4"), Неопределено); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.НайтиURIПространстваИмен("d2p1"), "ns2"); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.НайтиURIПространстваИмен("nsx"), Неопределено); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 2, "child4:end"); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns1"), Неопределено); + юТест.ПроверитьНеРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns2"), Неопределено); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns3"), Неопределено); + + // TODO: Несовместимость поведения чтения XML в .NET (*1) + // юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.URIПространствИмен().Найти("ns4"), Неопределено); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 1, "child2:end"); + + Чтение.Прочитать(); + юТест.ПроверитьРавенство(Чтение.КонтекстПространствИмен.Глубина, 0, "root:end"); + + // *1) При чтении пустого элемента на конце элемента Чтение должно забыть все пространства имён, + //установленные в начале элемента. + +КонецПроцедуры diff --git a/tests/xmlwrite.os b/tests/xmlwrite.os index 487b817d5..8107441b8 100644 --- a/tests/xmlwrite.os +++ b/tests/xmlwrite.os @@ -19,6 +19,7 @@ ВсеТесты.Добавить("ТестДолжен_ЗаписатьВСтроку"); ВсеТесты.Добавить("ТестДолжен_ЗаписатьВФайл"); ВсеТесты.Добавить("ТестДолжен_ЗаписатьСоответствиеПространстваИмен"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьКонтекстПространствИменВоВремяЗаписи"); Возврат ВсеТесты; КонецФункции @@ -124,3 +125,38 @@ Чтение.Закрыть(); КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКонтекстПространствИменВоВремяЗаписи() Экспорт + + ЗаписьXML = Новый ЗаписьXML; + ЗаписьXML.УстановитьСтроку(); + + // Проверим, что скрипт не падает, когда ничего не начали записывать + НеПадает = ЗаписьXML.КонтекстПространствИмен.СоответствияПространствИмен(); + + ЗаписьXML.ЗаписатьНачалоЭлемента("Корень"); + + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.Глубина, 1); + + ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("", "Пространство"); + ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("П1", "ЕщёПространство"); + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.ПространствоИменПоУмолчанию, "Пространство"); + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.НайтиURIПространстваИмен("П1"), "ЕщёПространство"); + + ЗаписьXML.ЗаписатьНачалоЭлемента("Дитё"); + + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.ПространствоИменПоУмолчанию, "Пространство"); + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.НайтиURIПространстваИмен("П1"), "ЕщёПространство"); + + ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("П2", "Пространство2"); + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.НайтиURIПространстваИмен("П2"), "Пространство2"); + + ЗаписьXML.ЗаписатьКонецЭлемента(); + + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.ПространствоИменПоУмолчанию, "Пространство"); + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.НайтиURIПространстваИмен("П1"), "ЕщёПространство"); + юТест.ПроверитьРавенство(ЗаписьXML.КонтекстПространствИмен.НайтиURIПространстваИмен("П2"), Неопределено); + + ЗаписьXML.ЗаписатьКонецЭлемента(); + +КонецПроцедуры From 9502cfb2783c2e961bdd41b113408440db82b678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D1=A3=D0=B9=20=D0=91=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Thu, 5 Jan 2017 21:07:52 +0300 Subject: [PATCH 30/63] =?UTF-8?q?`Equals()`=20=D1=81=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=B0=D0=BD=20=D0=B2=D0=B8=D1=80=D1=82=D1=83=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Метод `ContextIValueImpl.Equals(IValue)` сделан виртуальным, чтобы создаваемые классы могли переопределять поведение. Как пример - квалификаторы в Описании типов: объекты должны сравниваться по значениям полей, а не по ссылке. --- src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs index b391b1ce1..496beefa8 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs @@ -111,7 +111,7 @@ public int CompareTo(IValue other) #region IEquatable Members - public bool Equals(IValue other) + public virtual bool Equals(IValue other) { if (other.SystemType.Equals(this.SystemType)) { From f19fe62bd06e6f063d3ecfeff1cdfe9d3e53056f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D1=A3=D0=B9=20=D0=91=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Thu, 5 Jan 2017 21:31:34 +0300 Subject: [PATCH 31/63] =?UTF-8?q?`TypeTypeValue`=20=D1=81=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=20=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D1=8B=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Требуется для использования класса в ОписанииТипов. --- src/ScriptEngine/Machine/TypeTypeValue.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScriptEngine/Machine/TypeTypeValue.cs b/src/ScriptEngine/Machine/TypeTypeValue.cs index 54bd982c9..f0ac371e5 100644 --- a/src/ScriptEngine/Machine/TypeTypeValue.cs +++ b/src/ScriptEngine/Machine/TypeTypeValue.cs @@ -11,7 +11,7 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.Machine { - class TypeTypeValue : IValue + public class TypeTypeValue : IValue { TypeDescriptor _instance; From db31d71addb3b5130678e1d0c05568c176a6e129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D1=A3=D0=B9=20=D0=91=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Thu, 5 Jan 2017 22:53:56 +0300 Subject: [PATCH 32/63] =?UTF-8?q?=D0=92=20TypeTypeValue=20=D0=BE=D0=BF?= =?UTF-8?q?=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D1=8B=20Equals=20?= =?UTF-8?q?=D0=B8=20GetHashCode.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Требуются для внутренних нужд для правильного сравнения и поиска в коллекциях. --- src/ScriptEngine/Machine/TypeTypeValue.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ScriptEngine/Machine/TypeTypeValue.cs b/src/ScriptEngine/Machine/TypeTypeValue.cs index f0ac371e5..197845e4d 100644 --- a/src/ScriptEngine/Machine/TypeTypeValue.cs +++ b/src/ScriptEngine/Machine/TypeTypeValue.cs @@ -13,7 +13,7 @@ namespace ScriptEngine.Machine { public class TypeTypeValue : IValue { - TypeDescriptor _instance; + readonly TypeDescriptor _instance; public TypeTypeValue(string name) { @@ -83,6 +83,18 @@ public bool Equals(IValue other) } } + public override bool Equals(object obj) + { + if (obj is TypeTypeValue) + return Equals(obj as TypeTypeValue); + return false; + } + + public override int GetHashCode() + { + return _instance.GetHashCode(); + } + public TypeDescriptor Value { get From 3083a19f479051fab69ba7b8a0a57858b903f159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D1=A3=D0=B9=20=D0=91=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Fri, 6 Jan 2017 01:16:56 +0300 Subject: [PATCH 33/63] =?UTF-8?q?Fixes=20#182:=20=D0=9E=D0=B1=D1=8A=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=20`=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D0=B5=D0=A2=D0=B8=D0=BF=D0=BE=D0=B2`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Добавлены классы для классификаторов и для Описания Типа * Работает приведение простых типов * Добавлен тест --- src/1Script_Mono.sln | 4 +- .../TypeDescription/AllowedLengthEnum.cs | 19 ++ .../TypeDescription/AllowedSignEnum.cs | 19 ++ .../BinaryDataQualifiersImpl.cs | 58 +++++ .../TypeDescription/BooleanTypeAdjuster.cs | 29 +++ .../TypeDescription/DateFractionsEnum.cs | 22 ++ .../TypeDescription/DateQualifiersImpl.cs | 74 ++++++ .../Library/TypeDescription/IValueAdjuster.cs | 16 ++ .../TypeDescription/NumberQualifiersImpl.cs | 87 +++++++ .../TypeDescription/StringQualifiersImpl.cs | 87 +++++++ .../TypeDescription/TypeDescriptionImpl.cs | 245 ++++++++++++++++++ .../ScriptEngine.HostedScript.csproj | 13 + tests/typedescription.os | 200 ++++++++++++++ 13 files changed, 872 insertions(+), 1 deletion(-) create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedLengthEnum.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedSignEnum.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiersImpl.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/BooleanTypeAdjuster.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/DateFractionsEnum.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiersImpl.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/IValueAdjuster.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiersImpl.cs create mode 100644 src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs create mode 100644 tests/typedescription.os diff --git a/src/1Script_Mono.sln b/src/1Script_Mono.sln index 6d0913aea..790af0146 100644 --- a/src/1Script_Mono.sln +++ b/src/1Script_Mono.sln @@ -111,9 +111,11 @@ Global $1.ResourceNamePolicy = FileFormatDefault $0.TextStylePolicy = $2 $2.inheritsSet = null - $2.scope = application/xml + $2.scope = text/x-csharp $2.FileWidth = 120 $2.inheritsScope = text/plain + $2.TabsToSpaces = False + $2.NoTabsAfterNonTabs = True $0.CSharpFormattingPolicy = $3 $3.AfterDelegateDeclarationParameterComma = True $3.inheritsSet = Mono diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedLengthEnum.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedLengthEnum.cs new file mode 100644 index 000000000..93d47053e --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedLengthEnum.cs @@ -0,0 +1,19 @@ +/*---------------------------------------------------------- +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/. +----------------------------------------------------------*/ + +namespace ScriptEngine.HostedScript.Library +{ + [EnumerationType("ДопустимаяДлина", "AllowedLength")] + public enum AllowedLengthEnum + { + [EnumItem("Переменная", "Variable")] + Variable, + + [EnumItem("Фиксированная", "Fixed")] + Fixed + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedSignEnum.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedSignEnum.cs new file mode 100644 index 000000000..c3bd4f704 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/AllowedSignEnum.cs @@ -0,0 +1,19 @@ +/*---------------------------------------------------------- +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/. +----------------------------------------------------------*/ + +namespace ScriptEngine.HostedScript.Library +{ + [EnumerationType("ДопустимыйЗнак", "AllowedSign")] + public enum AllowedSignEnum + { + [EnumItem("Любой", "Any")] + Any, + + [EnumItem("Неотрицательный", "Nonnegative")] + Nonnegative + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiersImpl.cs new file mode 100644 index 000000000..16aad4849 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiersImpl.cs @@ -0,0 +1,58 @@ +/*---------------------------------------------------------- +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 ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.HostedScript.Library +{ + [ContextClass("КвалификаторыДвоичныхДанных", "BinaryDataQualifiers")] + public sealed class BinaryDataQualifiersImpl : AutoContext + { + public BinaryDataQualifiersImpl(int length = 0, + AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable) + { + Length = length; + AllowedLength = allowedLength; + } + + [ContextProperty("Длина")] + public int Length { get; } + + [ContextProperty("ДопустимаяДлина")] + public AllowedLengthEnum AllowedLength { get; } + + public override bool Equals(object obj) + { + var asThis = obj as BinaryDataQualifiersImpl; + if (asThis == null) + return false; + + return Length == asThis.Length + && AllowedLength == asThis.AllowedLength; + } + + public override bool Equals(IValue other) + { + return object.Equals(this, other?.GetRawValue()); + } + + public override int GetHashCode() + { + return Length.GetHashCode(); + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor(IValue length = null, + IValue allowedLength = null) + { + var paramLength = ContextValuesMarshaller.ConvertParam(length); + var paramAllowedLength = ContextValuesMarshaller.ConvertParam(allowedLength); + return new BinaryDataQualifiersImpl(paramLength, paramAllowedLength); + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/BooleanTypeAdjuster.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/BooleanTypeAdjuster.cs new file mode 100644 index 000000000..65919a444 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/BooleanTypeAdjuster.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 ScriptEngine.Machine; + +namespace ScriptEngine.HostedScript.Library +{ + public sealed class BooleanTypeAdjuster : IValueAdjuster + { + public IValue Adjust(IValue value) + { + if (value?.DataType == DataType.Boolean) + return value; + + try + { + // TODO: вменяемое приведение без Попытки + return ValueFactory.Create(value.AsBoolean()); + + } catch { } + + return ValueFactory.Create(false); + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/DateFractionsEnum.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/DateFractionsEnum.cs new file mode 100644 index 000000000..0a0294f05 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/DateFractionsEnum.cs @@ -0,0 +1,22 @@ +/*---------------------------------------------------------- +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/. +----------------------------------------------------------*/ + +namespace ScriptEngine.HostedScript.Library +{ + [EnumerationType("ЧастиДаты", "DateFractions")] + public enum DateFractionsEnum + { + [EnumItem("Дата", "Date")] + Date, + + [EnumItem("ДатаВремя", "DateTime")] + DateTime, + + [EnumItem("Время", "Time")] + Time + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiersImpl.cs new file mode 100644 index 000000000..fcf4873ff --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiersImpl.cs @@ -0,0 +1,74 @@ +/*---------------------------------------------------------- +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 ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.HostedScript.Library +{ + [ContextClass("КвалификаторыДаты", "DateQualifiers")] + public sealed class DateQualifiersImpl : AutoContext, IValueAdjuster + { + public DateQualifiersImpl(DateFractionsEnum dateFractions = DateFractionsEnum.Date) + { + DateFractions = dateFractions; + } + + [ContextProperty("ЧастиДаты")] + public DateFractionsEnum DateFractions { get; } + + public override bool Equals(object obj) + { + var asThis = obj as DateQualifiersImpl; + if (asThis == null) + return false; + + return DateFractions == asThis.DateFractions; + } + + public override bool Equals(IValue other) + { + return object.Equals(this, other?.GetRawValue()); + } + + public override int GetHashCode() + { + return DateFractions.GetHashCode(); + } + + public IValue Adjust(IValue value) + { + if (value == null || value.DataType == DataType.Undefined) + return ValueFactory.Create(new DateTime(1, 1, 1)); + + try + { + // TODO: вменяемое приведение без Попытки + var dateToAdjust = value.AsDate(); + + switch (DateFractions) + { + case DateFractionsEnum.Date: return ValueFactory.Create(dateToAdjust.Date); + case DateFractionsEnum.Time: return ValueFactory.Create(new DateTime(dateToAdjust.TimeOfDay.Ticks)); + default: return ValueFactory.Create(dateToAdjust); + } + } + catch + { + return ValueFactory.Create(new DateTime(1, 1, 1)); + } + + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor(IValue dateFractions = null) + { + var paramDateFractions = ContextValuesMarshaller.ConvertParam(dateFractions); + return new DateQualifiersImpl(paramDateFractions); + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/IValueAdjuster.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/IValueAdjuster.cs new file mode 100644 index 000000000..6ca8b5582 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/IValueAdjuster.cs @@ -0,0 +1,16 @@ +/*---------------------------------------------------------- +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 ScriptEngine.Machine; + +namespace ScriptEngine.HostedScript.Library +{ + public interface IValueAdjuster + { + IValue Adjust(IValue value); + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs new file mode 100644 index 000000000..e4ccc2619 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs @@ -0,0 +1,87 @@ +/*---------------------------------------------------------- +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 ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.HostedScript.Library +{ + [ContextClass("КвалификаторыЧисла", "NumberQualifiers")] + public sealed class NumberQualifiersImpl : AutoContext, IValueAdjuster + { + public NumberQualifiersImpl(int digits = 0, + int fractionDigits = 0, + AllowedSignEnum allowedSign = AllowedSignEnum.Any) + { + Digits = digits; + FractionDigits = fractionDigits; + AllowedSign = allowedSign; + } + + [ContextProperty("ДопустимыйЗнак")] + public AllowedSignEnum AllowedSign { get; } + + [ContextProperty("Разрядность")] + public int Digits { get; } + + [ContextProperty("РазрядностьДробнойЧасти")] + public int FractionDigits { get; } + + public override bool Equals(object obj) + { + var asThis = obj as NumberQualifiersImpl; + if (asThis == null) + return false; + + return Digits == asThis.Digits + && FractionDigits == asThis.FractionDigits + && AllowedSign == asThis.AllowedSign; + } + + public override bool Equals(IValue other) + { + return object.Equals(this, other?.GetRawValue()); + } + + public override int GetHashCode() + { + return Digits.GetHashCode(); + } + + public IValue Adjust(IValue value) + { + if (value == null) + { + // Значение по-умолчанию + return ValueFactory.Create(0); + } + // TODO: обрезать по количеству знаков + + try + { + // TODO: Вменяемое преобразование без Попытки + return ValueFactory.Create(value.AsNumber()); + + } catch + { + } + + return ValueFactory.Create(0); + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor(IValue digits = null, + IValue fractionDigits = null, + IValue allowedSign = null) + { + var paramDigits = ContextValuesMarshaller.ConvertParam(digits); + var paramFractionDigits = ContextValuesMarshaller.ConvertParam(fractionDigits); + var paramAllowedSign = ContextValuesMarshaller.ConvertParam(allowedSign); + return new NumberQualifiersImpl(paramDigits, paramFractionDigits, paramAllowedSign); + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiersImpl.cs new file mode 100644 index 000000000..c0d02d2b4 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiersImpl.cs @@ -0,0 +1,87 @@ +/*---------------------------------------------------------- +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 ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.HostedScript.Library +{ + [ContextClass("КвалификаторыСтроки", "StringQualifiers")] + public sealed class StringQualifiersImpl : AutoContext, IValueAdjuster + { + public StringQualifiersImpl(int length = 0, + AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable) + { + Length = length; + AllowedLength = allowedLength; + } + + [ContextProperty("Длина")] + public int Length { get; } + + [ContextProperty("ДопустимаяДлина")] + public AllowedLengthEnum AllowedLength { get; } + + public override bool Equals(object obj) + { + var asThis = obj as StringQualifiersImpl; + if (asThis == null) + return false; + + return Length == asThis.Length + && AllowedLength == asThis.AllowedLength; + } + + public override bool Equals(IValue other) + { + return object.Equals(this, other?.GetRawValue()); + } + + public override int GetHashCode() + { + return Length.GetHashCode(); + } + + public string DefaultString() + { + if (AllowedLength == AllowedLengthEnum.Variable) + return ""; + + if (Length == 0) + return ""; + + return new string(' ', Length); + } + + public IValue Adjust(IValue value) + { + var stringValue = value?.AsString() ?? ""; + + if (Length != 0 && stringValue.Length > Length) + { + stringValue = stringValue.Substring(0, Length); + } + + if (AllowedLength == AllowedLengthEnum.Fixed && stringValue.Length < Length) + { + var tail = new string(' ', Length - stringValue.Length); + stringValue = string.Format("{0}{1}", stringValue, tail); + } + + return ValueFactory.Create(stringValue); + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor(IValue length = null, + IValue allowedLength = null) + { + var paramLength = ContextValuesMarshaller.ConvertParam(length); + var paramAllowedLength = ContextValuesMarshaller.ConvertParam(allowedLength); + return new StringQualifiersImpl(paramLength, paramAllowedLength); + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs new file mode 100644 index 000000000..cbe3215b7 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs @@ -0,0 +1,245 @@ +/*---------------------------------------------------------- +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 ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; +using System.Collections.Generic; + +namespace ScriptEngine.HostedScript.Library +{ + [ContextClass("ОписаниеТипов", "TypeDescription")] + public class TypeDescriptionImpl : AutoContext + { + private readonly List _types = new List(); + + public TypeDescriptionImpl(IEnumerable types, + NumberQualifiersImpl numberQualifiers = null, + StringQualifiersImpl stringQualifiers = null, + DateQualifiersImpl dateQualifiers = null, + BinaryDataQualifiersImpl binaryDataQualifiers = null) + { + _types.AddRange(types); + NumberQualifiers = numberQualifiers ?? new NumberQualifiersImpl(); + StringQualifiers = stringQualifiers ?? new StringQualifiersImpl(); + DateQualifiers = dateQualifiers ?? new DateQualifiersImpl(); + BinaryDataQualifiers = binaryDataQualifiers ?? new BinaryDataQualifiersImpl(); + } + + [ContextProperty("КвалификаторыЧисла")] + public NumberQualifiersImpl NumberQualifiers { get; } + + [ContextProperty("КвалификаторыСтроки")] + public StringQualifiersImpl StringQualifiers { get; } + + [ContextProperty("КвалификаторыДаты")] + public DateQualifiersImpl DateQualifiers { get; } + + [ContextProperty("КвалификаторыДвоичныхДанных")] + public BinaryDataQualifiersImpl BinaryDataQualifiers { get; } + + [ContextMethod("Типы")] + public ArrayImpl Types() + { + var result = ArrayImpl.Constructor() as ArrayImpl; + + foreach (var type in _types) + { + result.Add(type); + } + + return result; + } + + [ContextMethod("СодержитТип")] + public bool ContainsType(IValue type) + { + if (type is TypeTypeValue) + return _types.IndexOf(type as TypeTypeValue) != -1; + throw RuntimeException.InvalidArgumentType(nameof(type)); + } + + IValueAdjuster GetAdjusterForType(TypeTypeValue type) + { + if (type.Value.Equals(TypeDescriptor.FromDataType(DataType.Number))) + return NumberQualifiers; + + if (type.Value.Equals(TypeDescriptor.FromDataType(DataType.String))) + return StringQualifiers; + + if (type.Value.Equals(TypeDescriptor.FromDataType(DataType.Date))) + return DateQualifiers; + + if (type.Value.Equals(TypeDescriptor.FromDataType(DataType.Boolean))) + return new BooleanTypeAdjuster(); + + return null; + } + + [ContextMethod("ПривестиЗначение")] + public IValue AdjustValue(IValue value = null) + { + + if (_types.Count == 0) + { + // нет типов - только Неопределено + return ValueFactory.Create(); + } + + TypeTypeValue typeToCast = null; + + if (value != null && value.DataType != DataType.Undefined) + { + var valueType = new TypeTypeValue(value.SystemType); + if (_types.Contains(valueType)) + { + // Если такой тип у нас есть + typeToCast = valueType; + } + } + + if (typeToCast == null) + { + // Если типа нет, то нужно брать значение по-умолчанию + if (_types.Count != 1) + { + // много типов - Неопределено + return ValueFactory.Create(); + } + + typeToCast = _types[0]; + } + + var adjuster = GetAdjusterForType(typeToCast); + + return adjuster?.Adjust(value) ?? ValueFactory.Create(); + } + + private static IList ConstructTypeList(IValue types) + { + var _types = new List(); + if (types == null) + return _types; + + types = types.GetRawValue(); + if (types.DataType == DataType.String) + { + var typeNames = types.AsString().Split(','); + foreach (var typeName in typeNames) + { + _types.Add(new TypeTypeValue(typeName.Trim())); + } + } else if (types is ArrayImpl) + { + foreach (var type in (types as ArrayImpl)) + { + var rawType = type.GetRawValue() as TypeTypeValue; + if (rawType == null) + return null; + + _types.Add(rawType); + } + } else + { + return null; + } + return _types; + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor( + IValue source = null, + IValue p1 = null, + IValue p2 = null, + IValue p3 = null, + IValue p4 = null, + IValue p5 = null, + IValue p6 = null) + { + var rawSource = source?.GetRawValue(); + + if (rawSource == null || rawSource.DataType == DataType.Undefined) + { + // первый параметр имеет право быть не задан только в таком конструкторе + return ConstructByOtherDescription(null, p1, p2, p3, p4, p5, p6); + } + + if (rawSource is TypeDescriptionImpl) + { + return ConstructByOtherDescription(rawSource, p1, p2, p3, p4, p5, p6); + } + + if (rawSource.DataType == DataType.String || rawSource is ArrayImpl) + { + // TODO: проверить, что p5 и p6 не заданы + return ConstructByQualifiers(rawSource, p1, p2, p3, p4); + } + + throw RuntimeException.InvalidArgumentValue(); + } + + public static IRuntimeContextInstance ConstructByQualifiers( + IValue types, + IValue numberQualifiers = null, + IValue stringQualifiers = null, + IValue dateQualifiers = null, + IValue binaryDataQualifiers = null) + { + var _types = ConstructTypeList(types); + if (_types == null) + throw RuntimeException.InvalidArgumentType(nameof(types)); + + var paramNumberQ = numberQualifiers?.GetRawValue() as NumberQualifiersImpl; + var paramStringQ = stringQualifiers?.GetRawValue() as StringQualifiersImpl; + var paramDateQ = dateQualifiers?.GetRawValue() as DateQualifiersImpl; + var paramBinaryDataQ = binaryDataQualifiers?.GetRawValue() as BinaryDataQualifiersImpl; + + return new TypeDescriptionImpl(_types, paramNumberQ, paramStringQ, paramDateQ, paramBinaryDataQ); + } + + public static IRuntimeContextInstance ConstructByOtherDescription( + IValue typeDescription = null, + IValue addTypes = null, + IValue removeTypes = null, + IValue numberQualifiers = null, + IValue stringQualifiers = null, + IValue dateQualifiers = null, + IValue binaryDataQualifiers = null) + { + var td = typeDescription as TypeDescriptionImpl; + + var removeTypesList = ConstructTypeList(removeTypes); + if (removeTypesList == null) + throw RuntimeException.InvalidArgumentType(nameof(removeTypes)); + + + var _types = new List(); + if (td != null) + { + foreach (var ivType in td.Types()) + { + var type = ivType as TypeTypeValue; + if (removeTypesList.IndexOf(type) == -1) + { + _types.Add(type); + } + } + } + + var addTypesList = ConstructTypeList(addTypes); + if (addTypesList == null) + throw RuntimeException.InvalidArgumentType(nameof(addTypes)); + _types.AddRange(addTypesList); + + var paramNumberQ = numberQualifiers?.GetRawValue() as NumberQualifiersImpl ?? td?.NumberQualifiers; + var paramStringQ = stringQualifiers?.GetRawValue() as StringQualifiersImpl ?? td?.StringQualifiers; + var paramDateQ = dateQualifiers?.GetRawValue() as DateQualifiersImpl ?? td?.DateQualifiers; + var paramBinaryDataQ = binaryDataQualifiers?.GetRawValue() as BinaryDataQualifiersImpl ?? td?.BinaryDataQualifiers; + + return new TypeDescriptionImpl(_types, paramNumberQ, paramStringQ, paramDateQ, paramBinaryDataQ); + } + } +} diff --git a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj index 420ffbed4..87878a8cb 100644 --- a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj +++ b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj @@ -199,6 +199,16 @@ + + + + + + + + + + @@ -213,6 +223,9 @@ + + + diff --git a/tests/typedescription.os b/tests/typedescription.os new file mode 100644 index 000000000..a1841e829 --- /dev/null +++ b/tests/typedescription.os @@ -0,0 +1,200 @@ +Перем юТест; + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + юТест = ЮнитТестирование; + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_ПроверитьКвалификаторыЧисла"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьКвалификаторыСтроки"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьКвалификаторыДаты"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьКвалификаторыДвоичныхДанных"); + + ВсеТесты.Добавить("ТестДолжен_СоздатьОписаниеТиповПоКвалификаторам"); + ВсеТесты.Добавить("ТестДолжен_СоздатьОписаниеТиповПоДругомуОписанию"); + + ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеСтрок"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеБулева"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеДат"); + + Возврат ВсеТесты; +КонецФункции + +Процедура ТестДолжен_ПроверитьКвалификаторыЧисла() Экспорт + + К1 = Новый КвалификаторыЧисла(10); + К2 = Новый КвалификаторыЧисла(10, 0); + К3 = Новый КвалификаторыЧисла(10, 0, ДопустимыйЗнак.Любой); + К4 = Новый КвалификаторыЧисла(10, 1); + + юТест.ПроверитьРавенство (К1, К2, "Квалификаторы с одинаковыми параметрами равны"); + юТест.ПроверитьРавенство (К1, К3, "Квалификаторы с одинаковыми параметрами равны"); + юТест.ПроверитьРавенство (К2, К3, "Квалификаторы с одинаковыми параметрами равны"); + юТест.ПроверитьНеРавенство(К1, К4, "Квалификаторы с разными параметрами не равны"); + + юТест.ПроверитьРавенство(К1.ДопустимыйЗнак, ДопустимыйЗнак.Любой); + юТест.ПроверитьРавенство(К1.РазрядностьДробнойЧасти, 0); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКвалификаторыСтроки() Экспорт + + К1 = Новый КвалификаторыСтроки(10); + К2 = Новый КвалификаторыСтроки(10, ДопустимаяДлина.Переменная); + К3 = Новый КвалификаторыСтроки(10, ДопустимаяДлина.Фиксированная); + + юТест.ПроверитьРавенство (К1, К2, "Квалификаторы с одинаковыми параметрами равны"); + юТест.ПроверитьНеРавенство(К1, К3, "Квалификаторы с разными параметрами не равны"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКвалификаторыДаты() Экспорт + + К1 = Новый КвалификаторыДаты(); + К2 = Новый КвалификаторыДаты(ЧастиДаты.Дата); + К3 = Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя); + К4 = Новый КвалификаторыДаты(ЧастиДаты.Время); + + юТест.ПроверитьРавенство (К1, К2, "Квалификаторы с одинаковыми параметрами равны"); + юТест.ПроверитьНеРавенство(К1, К3, "Квалификаторы с разными параметрами не равны"); + юТест.ПроверитьНеРавенство(К1, К4, "Квалификаторы с разными параметрами не равны"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьКвалификаторыДвоичныхДанных() Экспорт + + К1 = Новый КвалификаторыДвоичныхДанных(10); + К2 = Новый КвалификаторыДвоичныхДанных(10, ДопустимаяДлина.Переменная); + К3 = Новый КвалификаторыДвоичныхДанных(10, ДопустимаяДлина.Фиксированная); + + юТест.ПроверитьРавенство (К1, К2, "Квалификаторы с одинаковыми параметрами равны"); + юТест.ПроверитьНеРавенство(К1, К3, "Квалификаторы с разными параметрами не равны"); + +КонецПроцедуры + +Процедура ТестДолжен_СоздатьОписаниеТиповПоКвалификаторам() Экспорт + + Описание1 = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10)); + Описание2 = Новый ОписаниеТипов("Строка", Новый КвалификаторыЧисла(10)); + Описание3 = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(10)); + Описание4 = Новый ОписаниеТипов("Число,Строка", Новый КвалификаторыЧисла(20)); + + юТест.ПроверитьРавенство(Описание1.КвалификаторыЧисла, Описание2.КвалификаторыЧисла); + + // Значения по умолчанию должны совпасть + юТест.ПроверитьРавенство(Описание1.КвалификаторыСтроки, Описание2.КвалификаторыСтроки); + юТест.ПроверитьРавенство(Описание1.КвалификаторыДаты, Описание2.КвалификаторыДаты); + юТест.ПроверитьРавенство(Описание1.КвалификаторыДвоичныхДанных, Описание2.КвалификаторыДвоичныхДанных); + + юТест.ПроверитьРавенство(Описание1.Типы().Количество(), 1); + юТест.ПроверитьРавенство(Описание2.Типы().Количество(), 1); + юТест.ПроверитьРавенство(Описание3.Типы().Количество(), 1); + юТест.ПроверитьРавенство(Описание4.Типы().Количество(), 2); + +КонецПроцедуры + +Процедура ТестДолжен_СоздатьОписаниеТиповПоДругомуОписанию() Экспорт + + КЧ1 = Новый КвалификаторыЧисла(10); + КЧ2 = Новый КвалификаторыЧисла(20); + КС1 = Новый КвалификаторыСтроки(10); + КС2 = Новый КвалификаторыСтроки(20); + КД1 = Новый КвалификаторыДаты(ЧастиДаты.Дата); + КД2 = Новый КвалификаторыДаты(ЧастиДаты.Время); + КДД1 = Новый КвалификаторыДвоичныхДанных(10); + КДД2 = Новый КвалификаторыДвоичныхДанных(20); + + Описание1 = Новый ОписаниеТипов("Строка,Число", КЧ1, КС1, КД1, КДД1); + Описание2 = Новый ОписаниеТипов(Описание1, "Массив", "Число", КЧ2, КС2, КД2, КДД2); + + юТест.ПроверитьНеРавенство(Описание1.КвалификаторыЧисла, Описание2.КвалификаторыЧисла); + юТест.ПроверитьНеРавенство(Описание1.КвалификаторыСтроки, Описание2.КвалификаторыСтроки); + юТест.ПроверитьНеРавенство(Описание1.КвалификаторыДаты, Описание2.КвалификаторыДаты); + юТест.ПроверитьНеРавенство(Описание1.КвалификаторыДвоичныхДанных, Описание2.КвалификаторыДвоичныхДанных); + + юТест.ПроверитьРавенство(Описание2.Типы().Найти(Тип("Число")), Неопределено); + юТест.ПроверитьНеРавенство(Описание2.Типы().Найти(Тип("Массив")), Неопределено); + + юТест.ПроверитьРавенство(Описание2.СодержитТип(Тип("Число")), Ложь); + юТест.ПроверитьРавенство(Описание2.СодержитТип(Тип("Массив")), Истина); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПриведениеСтрок() Экспорт + + Описание1 = Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(5, ДопустимаяДлина.Фиксированная)); + + Значение = Описание1.ПривестиЗначение("123456"); + юТест.ПроверитьРавенство(Значение, "12345", "Усечение строки"); + + Значение = Описание1.ПривестиЗначение("123"); + юТест.ПроверитьРавенство(Значение, "123 ", "Расширение строки"); + + Значение = Описание1.ПривестиЗначение(Новый Массив); + юТест.ПроверитьРавенство(Значение, "Масси", "Неродное значение"); + + Значение = Описание1.ПривестиЗначение(1); + юТест.ПроверитьРавенство(Значение, "1 ", "Приведение числа"); + + Значение = Описание1.ПривестиЗначение(123456); + юТест.ПроверитьРавенство(Значение, "12345", "Приведение числа с усечением"); + + + Описание1 = Новый ОписаниеТипов("Строка",, Новый КвалификаторыСтроки(5, ДопустимаяДлина.Переменная)); + + Значение = Описание1.ПривестиЗначение("123456"); + юТест.ПроверитьРавенство(Значение, "12345", "Усечение строки"); + + Значение = Описание1.ПривестиЗначение("123"); + юТест.ПроверитьРавенство(Значение, "123", "Расширения строки нет"); + + Значение = Описание1.ПривестиЗначение(Новый Массив); + юТест.ПроверитьРавенство(Значение, "Масси", "Неродное значение"); + + Значение = Описание1.ПривестиЗначение(1); + юТест.ПроверитьРавенство(Значение, "1", "Приведение числа без расширения строки"); + + Значение = Описание1.ПривестиЗначение(123456); + юТест.ПроверитьРавенство(Значение, "12345", "Приведение числа с усечением"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПриведениеБулева() Экспорт + + Описание1 = Новый ОписаниеТипов("Булево"); + + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение(), Ложь, "Значение по-умолчанию"); + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение(Новый Массив), Ложь, "Неприводимое значение"); + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение(0), Ложь, "Число 0 = Ложь"); + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение(1), Истина, "Число 1 = Истина"); + + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение(132432), Истина, "Любое число не 0 = Истина"); + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение("Истина"), Истина, "Стрковое представление Истина"); + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение("Ложь"), Ложь, "Стрковое представление Ложь"); + + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение("false"), Ложь, "Стрковое представление false"); + юТест.ПроверитьРавенство(Описание1.ПривестиЗначение("true"), true, "Стрковое представление true"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПриведениеДат() Экспорт + + Описание_ДатаВремя = Новый ОписаниеТипов("Дата",,, Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)); + Описание_Дата = Новый ОписаниеТипов("Дата",,, Новый КвалификаторыДаты(ЧастиДаты.Дата)); + Описание_Время = Новый ОписаниеТипов("Дата",,, Новый КвалификаторыДаты(ЧастиДаты.Время)); + + ИсходноеЗначение = "20170106010114"; + Верное_ДатаВремя = '20170106010114'; + Верное_Дата = '20170106000000'; + Верное_Время = '00010101010114'; + + Значение_ДатаВремя = Описание_ДатаВремя.ПривестиЗначение(ИсходноеЗначение); + Значение_Дата = Описание_Дата.ПривестиЗначение(ИсходноеЗначение); + Значение_Время = Описание_Время.ПривестиЗначение(ИсходноеЗначение); + + юТест.ПроверитьРавенство(Значение_ДатаВремя, Верное_ДатаВремя, "Приведение без усечения"); + юТест.ПроверитьРавенство(Значение_Дата, Верное_Дата, "Усечение времени"); + юТест.ПроверитьРавенство(Значение_Время, Верное_Время, "Усечение даты"); + +КонецПроцедуры From ae86f14efefe735087b8aabedc9abc8f138eca9c Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Tue, 10 Jan 2017 16:19:25 +0300 Subject: [PATCH 34/63] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B0=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B2=D0=BE=D0=B7=D0=B2=D1=80=D0=B0=D1=82=D0=B0=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81=D1=82=D1=8B=D1=85=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D1=87=D0=B8=D1=81=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit В случае, если получалось значение параметра с типом enum, возникало исключение "Type is not supported". --- .../Machine/Contexts/ContextValuesMarshaller.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs b/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs index 6c00b339e..a8ff83e0a 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextValuesMarshaller.cs @@ -134,6 +134,13 @@ public static IValue ConvertReturnValue(TRet param) { return ValueFactory.Create((bool)objParam); } + else if (type.IsEnum) + { + var wrapperType = typeof(CLREnumValueWrapper<>).MakeGenericType(new Type[] { type }); + var constructor = wrapperType.GetConstructor(new Type[] { typeof(EnumerationContext), type, typeof(DataType) }); + var osValue = (EnumerationValue)constructor.Invoke(new object[] { null, param, DataType.Enumeration }); + return osValue; + } else if (typeof(IRuntimeContextInstance).IsAssignableFrom(type)) { if (objParam != null) From 980dec931b746a9412102d4955b25270b09b4635 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Wed, 11 Jan 2017 11:59:06 +0300 Subject: [PATCH 35/63] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=D0=A2=D0=B8=D0=BF=D0=BE=D0=B2:=20=D0=9F=D1=80?= =?UTF-8?q?=D0=B8=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D0=B5=D0=BB.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/1Script_Mono.sln | 3 +- .../TypeDescription/NumberQualifiersImpl.cs | 17 +++++++++- .../TypeDescription/TypeDescriptionImpl.cs | 3 +- tests/typedescription.os | 32 +++++++++++++++++++ 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/1Script_Mono.sln b/src/1Script_Mono.sln index 790af0146..9295a3ae9 100644 --- a/src/1Script_Mono.sln +++ b/src/1Script_Mono.sln @@ -111,11 +111,10 @@ Global $1.ResourceNamePolicy = FileFormatDefault $0.TextStylePolicy = $2 $2.inheritsSet = null - $2.scope = text/x-csharp + $2.scope = application/xml $2.FileWidth = 120 $2.inheritsScope = text/plain $2.TabsToSpaces = False - $2.NoTabsAfterNonTabs = True $0.CSharpFormattingPolicy = $3 $3.AfterDelegateDeclarationParameterComma = True $3.inheritsSet = Mono diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs index e4ccc2619..35b556b99 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs @@ -64,7 +64,16 @@ public IValue Adjust(IValue value) try { // TODO: Вменяемое преобразование без Попытки - return ValueFactory.Create(value.AsNumber()); + var numericValue = value.AsNumber(); + + if (AllowedSign == AllowedSignEnum.Nonnegative && numericValue < 0) + { + numericValue = 0; + } + + numericValue = Math.Round(numericValue, FractionDigits); + + return ValueFactory.Create(numericValue); } catch { @@ -80,6 +89,12 @@ public static IRuntimeContextInstance Constructor(IValue digits = null, { var paramDigits = ContextValuesMarshaller.ConvertParam(digits); var paramFractionDigits = ContextValuesMarshaller.ConvertParam(fractionDigits); + + if (paramDigits < 0 || paramFractionDigits < 0) + { + throw RuntimeException.InvalidArgumentValue(); + } + var paramAllowedSign = ContextValuesMarshaller.ConvertParam(allowedSign); return new NumberQualifiersImpl(paramDigits, paramFractionDigits, paramAllowedSign); } diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs index cbe3215b7..2c178cb1e 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs @@ -85,8 +85,7 @@ public IValue AdjustValue(IValue value = null) if (_types.Count == 0) { - // нет типов - только Неопределено - return ValueFactory.Create(); + return value; } TypeTypeValue typeToCast = null; diff --git a/tests/typedescription.os b/tests/typedescription.os index a1841e829..1942b887a 100644 --- a/tests/typedescription.os +++ b/tests/typedescription.os @@ -17,8 +17,11 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеСтрок"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеБулева"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеДат"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеБезПриведения"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьПриведениеЧисел"); Возврат ВсеТесты; + КонецФункции Процедура ТестДолжен_ПроверитьКвалификаторыЧисла() Экспорт @@ -198,3 +201,32 @@ юТест.ПроверитьРавенство(Значение_Время, Верное_Время, "Усечение даты"); КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПриведениеБезПриведения() Экспорт + + Описание = Новый ОписаниеТипов(Новый Массив); + + Значения = Новый Массив; + Значения.Добавить('20170111121212'); + Значения.Добавить("Строка 5"); + Значения.Добавить(14); + + Для Каждого ПроверяемоеЗначение Из Значения Цикл + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(ПроверяемоеЗначение), ПроверяемоеЗначение); + КонецЦикла; + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьПриведениеЧисел() Экспорт + + Описание = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 0, ДопустимыйЗнак.Неотрицательный)); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(-5), 0, "Обнуление отрицательных"); + + Описание = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2, ДопустимыйЗнак.Любой)); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(5.555), 5.56, "Округление"); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(5.554), 5.55, "Округление"); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(-5.554), -5.55, "Округление"); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(-5.555), -5.56, "Округление"); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(-5.55), -5.55, "Округление"); + +КонецПроцедуры From 3fb9c02424bbbc0f64ec979e8b7b9d94f22b5aef Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Thu, 12 Jan 2017 10:26:11 +0300 Subject: [PATCH 36/63] =?UTF-8?q?=D0=9E=D0=BF=D0=B8=D1=81=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=D0=A2=D0=B8=D0=BF=D0=BE=D0=B2:=20=D0=94=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=BC=D0=B5=D1=87=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ValueFormatter сделан публичным * Убран суффикс Impl * Добавлена обрезка чисел по общему количеству знаков --- ...lifiersImpl.cs => BinaryDataQualifiers.cs} | 8 +-- ...ateQualifiersImpl.cs => DateQualifiers.cs} | 8 +-- ...rQualifiersImpl.cs => NumberQualifiers.cs} | 14 ++--- ...gQualifiersImpl.cs => StringQualifiers.cs} | 8 +-- ...eDescriptionImpl.cs => TypeDescription.cs} | 52 +++++++++---------- .../ScriptEngine.HostedScript.csproj | 10 ++-- src/ScriptEngine/Machine/ValueFormatter.cs | 4 +- tests/typedescription.os | 6 +++ 8 files changed, 59 insertions(+), 51 deletions(-) rename src/ScriptEngine.HostedScript/Library/TypeDescription/{BinaryDataQualifiersImpl.cs => BinaryDataQualifiers.cs} (86%) rename src/ScriptEngine.HostedScript/Library/TypeDescription/{DateQualifiersImpl.cs => DateQualifiers.cs} (87%) rename src/ScriptEngine.HostedScript/Library/TypeDescription/{NumberQualifiersImpl.cs => NumberQualifiers.cs} (87%) rename src/ScriptEngine.HostedScript/Library/TypeDescription/{StringQualifiersImpl.cs => StringQualifiers.cs} (89%) rename src/ScriptEngine.HostedScript/Library/TypeDescription/{TypeDescriptionImpl.cs => TypeDescription.cs} (78%) diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiers.cs similarity index 86% rename from src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiersImpl.cs rename to src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiers.cs index 16aad4849..43f47c113 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiersImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/BinaryDataQualifiers.cs @@ -11,9 +11,9 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library { [ContextClass("КвалификаторыДвоичныхДанных", "BinaryDataQualifiers")] - public sealed class BinaryDataQualifiersImpl : AutoContext + public sealed class BinaryDataQualifiers : AutoContext { - public BinaryDataQualifiersImpl(int length = 0, + public BinaryDataQualifiers(int length = 0, AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable) { Length = length; @@ -28,7 +28,7 @@ public BinaryDataQualifiersImpl(int length = 0, public override bool Equals(object obj) { - var asThis = obj as BinaryDataQualifiersImpl; + var asThis = obj as BinaryDataQualifiers; if (asThis == null) return false; @@ -52,7 +52,7 @@ public static IRuntimeContextInstance Constructor(IValue length = null, { var paramLength = ContextValuesMarshaller.ConvertParam(length); var paramAllowedLength = ContextValuesMarshaller.ConvertParam(allowedLength); - return new BinaryDataQualifiersImpl(paramLength, paramAllowedLength); + return new BinaryDataQualifiers(paramLength, paramAllowedLength); } } } diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiers.cs similarity index 87% rename from src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiersImpl.cs rename to src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiers.cs index fcf4873ff..73d45db17 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiersImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/DateQualifiers.cs @@ -11,9 +11,9 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library { [ContextClass("КвалификаторыДаты", "DateQualifiers")] - public sealed class DateQualifiersImpl : AutoContext, IValueAdjuster + public sealed class DateQualifiers : AutoContext, IValueAdjuster { - public DateQualifiersImpl(DateFractionsEnum dateFractions = DateFractionsEnum.Date) + public DateQualifiers(DateFractionsEnum dateFractions = DateFractionsEnum.Date) { DateFractions = dateFractions; } @@ -23,7 +23,7 @@ public DateQualifiersImpl(DateFractionsEnum dateFractions = DateFractionsEnum.Da public override bool Equals(object obj) { - var asThis = obj as DateQualifiersImpl; + var asThis = obj as DateQualifiers; if (asThis == null) return false; @@ -68,7 +68,7 @@ public IValue Adjust(IValue value) public static IRuntimeContextInstance Constructor(IValue dateFractions = null) { var paramDateFractions = ContextValuesMarshaller.ConvertParam(dateFractions); - return new DateQualifiersImpl(paramDateFractions); + return new DateQualifiers(paramDateFractions); } } } diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiers.cs similarity index 87% rename from src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs rename to src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiers.cs index 35b556b99..84493f2cd 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiersImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/NumberQualifiers.cs @@ -11,9 +11,9 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library { [ContextClass("КвалификаторыЧисла", "NumberQualifiers")] - public sealed class NumberQualifiersImpl : AutoContext, IValueAdjuster + public sealed class NumberQualifiers : AutoContext, IValueAdjuster { - public NumberQualifiersImpl(int digits = 0, + public NumberQualifiers(int digits = 0, int fractionDigits = 0, AllowedSignEnum allowedSign = AllowedSignEnum.Any) { @@ -33,7 +33,7 @@ public NumberQualifiersImpl(int digits = 0, public override bool Equals(object obj) { - var asThis = obj as NumberQualifiersImpl; + var asThis = obj as NumberQualifiers; if (asThis == null) return false; @@ -71,8 +71,10 @@ public IValue Adjust(IValue value) numericValue = 0; } - numericValue = Math.Round(numericValue, FractionDigits); - + if (Digits > 0) + { + ValueFormatter.ApplyNumericSizeRestrictions(ref numericValue, Digits, FractionDigits); + } return ValueFactory.Create(numericValue); } catch @@ -96,7 +98,7 @@ public static IRuntimeContextInstance Constructor(IValue digits = null, } var paramAllowedSign = ContextValuesMarshaller.ConvertParam(allowedSign); - return new NumberQualifiersImpl(paramDigits, paramFractionDigits, paramAllowedSign); + return new NumberQualifiers(paramDigits, paramFractionDigits, paramAllowedSign); } } } diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiersImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiers.cs similarity index 89% rename from src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiersImpl.cs rename to src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiers.cs index c0d02d2b4..52681837c 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiersImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/StringQualifiers.cs @@ -11,9 +11,9 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library { [ContextClass("КвалификаторыСтроки", "StringQualifiers")] - public sealed class StringQualifiersImpl : AutoContext, IValueAdjuster + public sealed class StringQualifiers : AutoContext, IValueAdjuster { - public StringQualifiersImpl(int length = 0, + public StringQualifiers(int length = 0, AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable) { Length = length; @@ -28,7 +28,7 @@ public StringQualifiersImpl(int length = 0, public override bool Equals(object obj) { - var asThis = obj as StringQualifiersImpl; + var asThis = obj as StringQualifiers; if (asThis == null) return false; @@ -81,7 +81,7 @@ public static IRuntimeContextInstance Constructor(IValue length = null, { var paramLength = ContextValuesMarshaller.ConvertParam(length); var paramAllowedLength = ContextValuesMarshaller.ConvertParam(allowedLength); - return new StringQualifiersImpl(paramLength, paramAllowedLength); + return new StringQualifiers(paramLength, paramAllowedLength); } } } diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescription.cs similarity index 78% rename from src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs rename to src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescription.cs index 2c178cb1e..a8f15d34a 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescriptionImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescription.cs @@ -12,34 +12,34 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library { [ContextClass("ОписаниеТипов", "TypeDescription")] - public class TypeDescriptionImpl : AutoContext + public class TypeDescription : AutoContext { private readonly List _types = new List(); - public TypeDescriptionImpl(IEnumerable types, - NumberQualifiersImpl numberQualifiers = null, - StringQualifiersImpl stringQualifiers = null, - DateQualifiersImpl dateQualifiers = null, - BinaryDataQualifiersImpl binaryDataQualifiers = null) + public TypeDescription(IEnumerable types, + NumberQualifiers numberQualifiers = null, + StringQualifiers stringQualifiers = null, + DateQualifiers dateQualifiers = null, + BinaryDataQualifiers binaryDataQualifiers = null) { _types.AddRange(types); - NumberQualifiers = numberQualifiers ?? new NumberQualifiersImpl(); - StringQualifiers = stringQualifiers ?? new StringQualifiersImpl(); - DateQualifiers = dateQualifiers ?? new DateQualifiersImpl(); - BinaryDataQualifiers = binaryDataQualifiers ?? new BinaryDataQualifiersImpl(); + NumberQualifiers = numberQualifiers ?? new NumberQualifiers(); + StringQualifiers = stringQualifiers ?? new StringQualifiers(); + DateQualifiers = dateQualifiers ?? new DateQualifiers(); + BinaryDataQualifiers = binaryDataQualifiers ?? new BinaryDataQualifiers(); } [ContextProperty("КвалификаторыЧисла")] - public NumberQualifiersImpl NumberQualifiers { get; } + public NumberQualifiers NumberQualifiers { get; } [ContextProperty("КвалификаторыСтроки")] - public StringQualifiersImpl StringQualifiers { get; } + public StringQualifiers StringQualifiers { get; } [ContextProperty("КвалификаторыДаты")] - public DateQualifiersImpl DateQualifiers { get; } + public DateQualifiers DateQualifiers { get; } [ContextProperty("КвалификаторыДвоичныхДанных")] - public BinaryDataQualifiersImpl BinaryDataQualifiers { get; } + public BinaryDataQualifiers BinaryDataQualifiers { get; } [ContextMethod("Типы")] public ArrayImpl Types() @@ -166,7 +166,7 @@ public static IRuntimeContextInstance Constructor( return ConstructByOtherDescription(null, p1, p2, p3, p4, p5, p6); } - if (rawSource is TypeDescriptionImpl) + if (rawSource is TypeDescription) { return ConstructByOtherDescription(rawSource, p1, p2, p3, p4, p5, p6); } @@ -191,12 +191,12 @@ public static IRuntimeContextInstance ConstructByQualifiers( if (_types == null) throw RuntimeException.InvalidArgumentType(nameof(types)); - var paramNumberQ = numberQualifiers?.GetRawValue() as NumberQualifiersImpl; - var paramStringQ = stringQualifiers?.GetRawValue() as StringQualifiersImpl; - var paramDateQ = dateQualifiers?.GetRawValue() as DateQualifiersImpl; - var paramBinaryDataQ = binaryDataQualifiers?.GetRawValue() as BinaryDataQualifiersImpl; + var paramNumberQ = numberQualifiers?.GetRawValue() as NumberQualifiers; + var paramStringQ = stringQualifiers?.GetRawValue() as StringQualifiers; + var paramDateQ = dateQualifiers?.GetRawValue() as DateQualifiers; + var paramBinaryDataQ = binaryDataQualifiers?.GetRawValue() as BinaryDataQualifiers; - return new TypeDescriptionImpl(_types, paramNumberQ, paramStringQ, paramDateQ, paramBinaryDataQ); + return new TypeDescription(_types, paramNumberQ, paramStringQ, paramDateQ, paramBinaryDataQ); } public static IRuntimeContextInstance ConstructByOtherDescription( @@ -208,7 +208,7 @@ public static IRuntimeContextInstance ConstructByOtherDescription( IValue dateQualifiers = null, IValue binaryDataQualifiers = null) { - var td = typeDescription as TypeDescriptionImpl; + var td = typeDescription as TypeDescription; var removeTypesList = ConstructTypeList(removeTypes); if (removeTypesList == null) @@ -233,12 +233,12 @@ public static IRuntimeContextInstance ConstructByOtherDescription( throw RuntimeException.InvalidArgumentType(nameof(addTypes)); _types.AddRange(addTypesList); - var paramNumberQ = numberQualifiers?.GetRawValue() as NumberQualifiersImpl ?? td?.NumberQualifiers; - var paramStringQ = stringQualifiers?.GetRawValue() as StringQualifiersImpl ?? td?.StringQualifiers; - var paramDateQ = dateQualifiers?.GetRawValue() as DateQualifiersImpl ?? td?.DateQualifiers; - var paramBinaryDataQ = binaryDataQualifiers?.GetRawValue() as BinaryDataQualifiersImpl ?? td?.BinaryDataQualifiers; + var paramNumberQ = numberQualifiers?.AsObject() as NumberQualifiers ?? td?.NumberQualifiers; + var paramStringQ = stringQualifiers?.AsObject() as StringQualifiers ?? td?.StringQualifiers; + var paramDateQ = dateQualifiers?.AsObject() as DateQualifiers ?? td?.DateQualifiers; + var paramBinaryDataQ = binaryDataQualifiers?.AsObject() as BinaryDataQualifiers ?? td?.BinaryDataQualifiers; - return new TypeDescriptionImpl(_types, paramNumberQ, paramStringQ, paramDateQ, paramBinaryDataQ); + return new TypeDescription(_types, paramNumberQ, paramStringQ, paramDateQ, paramBinaryDataQ); } } } diff --git a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj index 87878a8cb..5c57b275f 100644 --- a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj +++ b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj @@ -202,11 +202,11 @@ - - - - - + + + + + diff --git a/src/ScriptEngine/Machine/ValueFormatter.cs b/src/ScriptEngine/Machine/ValueFormatter.cs index e5c623b08..d7ebe71bc 100644 --- a/src/ScriptEngine/Machine/ValueFormatter.cs +++ b/src/ScriptEngine/Machine/ValueFormatter.cs @@ -12,7 +12,7 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.Machine { - static class ValueFormatter + public static class ValueFormatter { static readonly string[] BOOLEAN_FALSE = { "БЛ", "BF" }; static readonly string[] BOOLEAN_TRUE = { "БИ", "BT" }; @@ -221,7 +221,7 @@ private static int GetCharInteger(char digit) return (int)digit - 0x30; // keycode offset } - private static void ApplyNumericSizeRestrictions(ref decimal p, int totalDigits, int fractionDigits) + public static void ApplyNumericSizeRestrictions(ref decimal p, int totalDigits, int fractionDigits) { if (totalDigits == 0) return; diff --git a/tests/typedescription.os b/tests/typedescription.os index 1942b887a..e58c5d980 100644 --- a/tests/typedescription.os +++ b/tests/typedescription.os @@ -229,4 +229,10 @@ юТест.ПроверитьРавенство(Описание.ПривестиЗначение(-5.555), -5.56, "Округление"); юТест.ПроверитьРавенство(Описание.ПривестиЗначение(-5.55), -5.55, "Округление"); + Описание = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(0, 0, ДопустимыйЗнак.Любой)); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(12345.555), 12345.555, "Не режет ничего"); + + Описание = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(5, 2, ДопустимыйЗнак.Любой)); + юТест.ПроверитьРавенство(Описание.ПривестиЗначение(12345.555), 999.99, "Забивает девятками"); + КонецПроцедуры From 4df4c48091d209319a358bee9d3983f04ae78748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=BE=D1=81=D0=BD=D0=B0=20=D0=95=D0=B2=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B9?= Date: Thu, 12 Jan 2017 11:08:39 +0300 Subject: [PATCH 37/63] =?UTF-8?q?#183=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=B0=D0=BA?= =?UTF-8?q?=D0=B5=D1=82=D0=B0=20choco?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- install/choco/onescript.nuspec | 35 ++++++++ install/choco/tools/ReadMe.md | 91 +++++++++++++++++++++ install/choco/tools/chocolateyinstall.ps1 | 90 ++++++++++++++++++++ install/choco/tools/chocolateyuninstall.ps1 | 61 ++++++++++++++ 4 files changed, 277 insertions(+) create mode 100644 install/choco/onescript.nuspec create mode 100644 install/choco/tools/ReadMe.md create mode 100644 install/choco/tools/chocolateyinstall.ps1 create mode 100644 install/choco/tools/chocolateyuninstall.ps1 diff --git a/install/choco/onescript.nuspec b/install/choco/onescript.nuspec new file mode 100644 index 000000000..09c54bd4d --- /dev/null +++ b/install/choco/onescript.nuspec @@ -0,0 +1,35 @@ + + + + + + onescript + onescript (Install) + __REPLACE__ + __REPLACE_AUTHORS_OF_SOFTWARE_COMMA_SEPARATED__ + __REPLACE_YOUR_NAME__ + __REPLACE__ + __REPLACE__MarkDown_Okay + + + + + onescript admin SPACE_SEPARATED + + + false + + + __REPLACE_OR_REMOVE__MarkDown_Okay + + + + + + diff --git a/install/choco/tools/ReadMe.md b/install/choco/tools/ReadMe.md new file mode 100644 index 000000000..e9d10ef2b --- /dev/null +++ b/install/choco/tools/ReadMe.md @@ -0,0 +1,91 @@ +## Summary +How do I create packages? See https://github.com/chocolatey/choco/wiki/CreatePackages + +If you are submitting packages to the community feed (https://chocolatey.org) +always try to ensure you have read, understood and adhere to the create +packages wiki link above. + +## Automatic Packages? +Consider making this package an automatic package, for the best +maintainability over time. Read up at https://github.com/chocolatey/choco/wiki/AutomaticPackages + +## Shim Generation +Any executables you include in the package or download (but don't call +install against using the built-in functions) will be automatically shimmed. + +This means those executables will automatically be included on the path. +Shim generation runs whether the package is self-contained or uses automation +scripts. + +By default, these are considered console applications. + +If the application is a GUI, you should create an empty file next to the exe +named 'name.exe.gui' e.g. 'bob.exe' would need a file named 'bob.exe.gui'. +See https://github.com/chocolatey/choco/wiki/CreatePackages#how-do-i-set-up-batch-redirects-for-applications-that-have-a-gui + +If you want to ignore the executable, create an empty file next to the exe +named 'name.exe.ignore' e.g. 'bob.exe' would need a file named +'bob.exe.ignore'. +See https://github.com/chocolatey/choco/wiki/CreatePackages#how-do-i-exclude-executables-from-getting-batch-redirects + +## Self-Contained? +If you have a self-contained package, you can remove the automation scripts +entirely and just include the executables, they will automatically get shimmed, +which puts them on the path. Ensure you have the legal right to distribute +the application though. See https://github.com/chocolatey/choco/wiki/Legal. + +You should read up on the Shim Generation section to familiarize yourself +on what to do with GUI applications and/or ignoring shims. + +## Automation Scripts +You have a powerful use of Chocolatey, as you are using PowerShell. So you +can do just about anything you need. Choco has some very handy built-in +functions that you can use, these are sometimes called the helpers. + +### Built-In Functions +https://github.com/chocolatey/choco/wiki/HelpersReference + +A note about a couple: +* Get-BinRoot - this is a horribly named function that doesn't do what new folks think it does. It gets you the 'tools' root, which by default is set to 'c:\tools', not the chocolateyInstall bin folder. +* Install-BinFile - used for non-exe files - executables are automatically shimmed... +* Uninstall-BinFile - used for non-exe files - executables are automatically shimmed + +### Getting package specific information +Use the package parameters pattern - see https://github.com/chocolatey/choco/wiki/How-To-Parse-PackageParameters-Argument + +### Need to mount an ISO? +https://github.com/chocolatey/choco/wiki/How-To-Mount-An-Iso-In-Chocolatey-Package + + +### Environment Variables +Chocolatey makes a number of environment variables available (You can access any of these with $env:TheVariableNameBelow): + + * TEMP = Overridden to the CacheLocation, but may be the same as the original TEMP folder + * ChocolateyInstall = Top level folder where Chocolatey is installed + * chocolateyPackageName = The name of the package, equivalent to the id in the nuspec (0.9.9+) + * chocolateyPackageVersion = The version of the package, equivalent to the version in the nuspec (0.9.9+) + * chocolateyPackageFolder = The top level location of the package folder + +#### Advanced Environment Variables +The following are more advanced settings: + + * chocolateyPackageParameters = (0.9.8.22+) + * CHOCOLATEY_VERSION = The version of Choco you normally see. Use if you are 'lighting' things up based on choco version. (0.9.9+) + - Otherwise take a dependency on the specific version you need. + * chocolateyForceX86 = If available and set to 'true', then user has requested 32bit version. (0.9.9+) + - Automatically handled in built in Choco functions. + * OS_PLATFORM = Like Windows, OSX, Linux. (0.9.9+) + * OS_VERSION = The version of OS, like 6.1 something something for Windows. (0.9.9+) + * OS_NAME = The reported name of the OS. (0.9.9+) + * IS_PROCESSELEVATED = Is the process elevated? (0.9.9+) + +#### Experimental Environment Variables +The following are experimental or use not recommended: + + * OS_IS64BIT = This may not return correctly - it may depend on the process the app is running under (0.9.9+) + * CHOCOLATEY_VERSION_PRODUCT = the version of Choco that may match CHOCOLATEY_VERSION but may be different (0.9.9+) + - it's based on git describe + * IS_ADMIN = Is the user an administrator? But doesn't tell you if the process is elevated. (0.9.9+) + * chocolateyInstallOverride = Not for use in package automation scripts. (0.9.9+) + * chocolateyInstallArguments = the installer arguments meant for the native installer. You should use chocolateyPackageParameters intead. (0.9.9+) + diff --git a/install/choco/tools/chocolateyinstall.ps1 b/install/choco/tools/chocolateyinstall.ps1 new file mode 100644 index 000000000..0748cbf8a --- /dev/null +++ b/install/choco/tools/chocolateyinstall.ps1 @@ -0,0 +1,90 @@ +#NOTE: Please remove any commented lines to tidy up prior to releasing the package, including this one +# REMOVE ANYTHING BELOW THAT IS NOT NEEDED + +$ErrorActionPreference = 'Stop'; # stop on all errors + + +$packageName = 'onescript' # arbitrary name for the package, used in messages +$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" +$url = 'http://oscript.io/downloads/latest/msi' # download url +$url64 = '' # 64bit URL here or remove - if installer is both, use $url + +$packageArgs = @{ + packageName = $packageName + unzipLocation = $toolsDir + fileType = 'EXE_MSI_OR_MSU' #only one of these: exe, msi, msu + url = $url + url64bit = $url64 + + #MSI + silentArgs = "/qn /norestart /l*v '$env:TEMP\chocolatey\$packageName\install.log'" # ALLUSERS=1 DISABLEDESKTOPSHORTCUT=1 ADDDESKTOPICON=0 ADDSTARTMENU=0 + validExitCodes= @(0, 3010, 1641) + #OTHERS + #silentArgs ='/S' # "/s /S /q /Q /quiet /silent /SILENT /VERYSILENT -s" # try any of these to get the silent installer + #validExitCodes= @(0) #please insert other valid exit codes here + + # optional + registryUninstallerKey = 'onescript' #ensure this is the value in the registry + checksum = '' + checksumType = 'md5' #default is md5, can also be sha1 + checksum64 = '' + checksumType64= 'md5' #default is checksumType +} + +Install-ChocolateyPackage @packageArgs +#Install-ChocolateyZipPackage @packageArgs + +## Main helper functions - these have error handling tucked into them already +## see https://github.com/chocolatey/choco/wiki/HelpersReference + +## Install an application, will assert administrative rights +## add additional optional arguments as necessary +##Install-ChocolateyPackage $packageName $fileType $silentArgs $url [$url64 -validExitCodes $validExitCodes -checksum $checksum -checksumType $checksumType -checksum64 $checksum64 -checksumType64 $checksumType64] + +## Download and unpack a zip file +##Install-ChocolateyZipPackage $packageName $url $toolsDir [$url64 -checksum $checksum -checksumType $checksumType -checksum64 $checksum64 -checksumType64 $checksumType64] + +## Install Visual Studio Package +#Install-ChocolateyVsixPackage $packageName $url [$vsVersion] [-checksum $checksum -checksumType $checksumType] +#Install-ChocolateyVsixPackage @packageArgs + +# see the full list at https://github.com/chocolatey/choco/wiki/HelpersReference +# downloader that the main helpers use to download items +# if removing $url64, please remove from here +#Get-ChocolateyWebFile $packageName 'DOWNLOAD_TO_FILE_FULL_PATH' $url $url64 +# installer, will assert administrative rights - used by Install-ChocolateyPackage +#Install-ChocolateyInstallPackage $packageName $fileType $silentArgs '_FULLFILEPATH_' -validExitCodes $validExitCodes +# unzips a file to the specified location - auto overwrites existing content +#Get-ChocolateyUnzip "FULL_LOCATION_TO_ZIP.zip" $toolsDir +# Runs processes asserting UAC, will assert administrative rights - used by Install-ChocolateyInstallPackage +#Start-ChocolateyProcessAsAdmin 'STATEMENTS_TO_RUN' 'Optional_Application_If_Not_PowerShell' -validExitCodes $validExitCodes +# add specific folders to the path - any executables found in the chocolatey package folder will already be on the path. This is used in addition to that or for cases when a native installer doesn't add things to the path. +#Install-ChocolateyPath 'LOCATION_TO_ADD_TO_PATH' 'User_OR_Machine' # Machine will assert administrative rights +# add specific files as shortcuts to the desktop +#$target = Join-Path $toolsDir "$($packageName).exe" +# Install-ChocolateyShortcut -shortcutFilePath "" -targetPath "" [-workDirectory "C:\" -arguments "C:\test.txt" -iconLocation "C:\test.ico" -description "This is the description"] +# outputs the bitness of the OS (either "32" or "64") +#$osBitness = Get-ProcessorBits +#Install-ChocolateyEnvironmentVariable -variableName "SOMEVAR" -variableValue "value" [-variableType = 'Machine' #Defaults to 'User'] + +#Install-ChocolateyFileAssociation +#Install-BinFile ## only use this for non-exe files - chocolatey will automatically pick up the exe files and shim them automatically +## https://github.com/chocolatey/choco/wiki/CreatePackages#how-do-i-exclude-executables-from-getting-batch-redirects + +##PORTABLE EXAMPLE +#$toolsDir = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)" +# despite the name "Install-ChocolateyZipPackage" this also works with 7z archives +#Install-ChocolateyZipPackage $packageName $url $toolsDir $url64 +## END PORTABLE EXAMPLE + +## [DEPRECATING] PORTABLE EXAMPLE +#$binRoot = Get-BinRoot +#$installDir = Join-Path $binRoot "$packageName" +#Write-Host "Adding `'$installDir`' to the path and the current shell path" +#Install-ChocolateyPath "$installDir" +#$env:Path = "$($env:Path);$installDir" + +# if removing $url64, please remove from here +# despite the name "Install-ChocolateyZipPackage" this also works with 7z archives +#Install-ChocolateyZipPackage "$packageName" "$url" "$installDir" "$url64" +## END PORTABLE EXAMPLE diff --git a/install/choco/tools/chocolateyuninstall.ps1 b/install/choco/tools/chocolateyuninstall.ps1 new file mode 100644 index 000000000..0fa02081d --- /dev/null +++ b/install/choco/tools/chocolateyuninstall.ps1 @@ -0,0 +1,61 @@ +#NOTE: Please remove any commented lines to tidy up prior to releasing the package, including this one +# REMOVE ANYTHING BELOW THAT IS NOT NEEDED +# Auto Uninstaller should be able to detect and handle registry uninstalls (if it is turned on, it is in preview for 0.9.9). + +$ErrorActionPreference = 'Stop'; # stop on all errors + +$packageName = 'onescript' +# registry uninstaller key name is the key that is found at HKLM:\Software\Windows\CurrentVersion\Uninstall\ THE NAME +$registryUninstallerKeyName = 'onescript' #ensure this is the value in the registry +$msiProductCodeGuid = '{insert it here}' +$shouldUninstall = $true + +$local_key = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName" +# local key 6432 probably never exists +$local_key6432 = "HKCU:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName" +$machine_key = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName" +$machine_key6432 = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\$registryUninstallerKeyName" + +$file = @($local_key, $local_key6432, $machine_key, $machine_key6432) ` + | ?{ Test-Path $_ } ` + | Get-ItemProperty ` + | Select-Object -ExpandProperty UninstallString + +if ($file -eq $null -or $file -eq '') { + Write-Host "$packageName has already been uninstalled by other means." + $shouldUninstall = $false +} + +# The below is somewhat naive and built for EXE installers +#$installerType = 'EXE' +#$silentArgs = '/S' +#$validExitCodes = @(0) + +#if (!(Test-Path $file)) { +# Write-Host "$packageName has already been uninstalled by other means." +# $shouldUninstall = $false +#} + +# The below is somewhat naive and built for MSI installers +$installerType = 'MSI' +# The Product Code GUID is all that should be passed for MSI, and very FIRST, +# because it comes directly after /x, which is already set in the +# Uninstall-ChocolateyPackage msiargs (facepalm). +$silentArgs = "$msiProductCodeGuid /qn /norestart" +# https://msdn.microsoft.com/en-us/library/aa376931(v=vs.85).aspx +$validExitCodes = @(0, 3010, 1605, 1614, 1641) +# Don't pass anything for file, it is ignored for msi (facepalm number 2) +# Alternatively if you need to pass a path to an msi, determine that and use +# it instead of $msiProductCodeGuid in silentArgs, still very first +$file = '' + +if ($shouldUninstall) { + Uninstall-ChocolateyPackage -PackageName $packageName -FileType $installerType -SilentArgs $silentArgs -validExitCodes $validExitCodes -File $file +} + +## OTHER HELPERS +## https://github.com/chocolatey/choco/wiki/HelpersReference +#Uninstall-ChocolateyZipPackage +#Uninstall-BinFile # Only needed if you added one in the installer script, choco will remove the ones it added automatically. +#remove any shortcuts you added + From cbac1a9ae085490bb7165a9bd6e09ac6f07eefb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D1=A3=D0=B9=20=D0=91=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D0=BD=D0=BE=D0=B2?= Date: Sat, 14 Jan 2017 22:55:59 +0300 Subject: [PATCH 38/63] =?UTF-8?q?Fixes=20#390:=20=D0=A3=D1=82=D0=BE=D1=87?= =?UTF-8?q?=D0=BD=D1=91=D0=BD=20=D1=81=D0=BE=D1=81=D1=82=D0=B0=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=BB=D0=B0=D0=B4=D0=BE=D1=87=D0=BD=D0=BE=D0=B3?= =?UTF-8?q?=D0=BE=20=D0=B1=D0=B0=D0=B9=D1=82-=D0=BA=D0=BE=D0=B4=D0=B0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Параметр isExtraCode применён в местах, где байт-код не влияет на выполнение или вывод данных об исключении. --- src/ScriptEngine/Compiler/Compiler.cs | 85 ++++++++++++++------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index f60be0d08..0d6fc3fd5 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -314,7 +314,7 @@ private void HandleDirective(bool codeEntered) private void BuildSingleMethod() { var entryPoint = _module.Code.Count; - AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber, isExtraCode: true); if (_lastExtractedLexem.Token == Token.Procedure) { @@ -506,7 +506,7 @@ private void DispatchMethodBody() if (_lastExtractedLexem.Token == Token.EndProcedure || _lastExtractedLexem.Token == Token.EndFunction) { - AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber, isExtraCode: true); } AddCommand(OperationCode.Return, 0); @@ -745,8 +745,10 @@ private void BuildForEachStatement() SetTryBlockFlag(savedTryFlag); PopStructureToken(); - if (_lastExtractedLexem.Token == Token.EndLoop) - AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + if (_lastExtractedLexem.Token == Token.EndLoop) + { + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber, isExtraCode: true); + } AddCommand(OperationCode.Jmp, loopBegin); var cmd = _module.Code[condition]; @@ -808,13 +810,15 @@ private void BuildCountableForStatement() SetTryBlockFlag(savedTryFlag); PopStructureToken(); - if (_lastExtractedLexem.Token == Token.EndLoop) - AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + if (_lastExtractedLexem.Token == Token.EndLoop) + { + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber, isExtraCode: true); + } // jmp to start AddCommand(OperationCode.Jmp, indexLoopBegin); var indexLoopEnd = AddCommand(OperationCode.PopTmp, 1); - + var cmd = _module.Code[conditionIndex]; cmd.Argument = indexLoopEnd; _module.Code[conditionIndex] = cmd; @@ -822,33 +826,34 @@ private void BuildCountableForStatement() CorrectBreakStatements(_nestedLoops.Pop(), indexLoopEnd); NextToken(); - } - - private void BuildWhileStatement() - { - NextToken(); - var conditionIndex = _module.Code.Count; - var loopRecord = NestedLoopInfo.New(); - loopRecord.startPoint = conditionIndex; - _nestedLoops.Push(loopRecord); - BuildExpression(Token.Loop); - PushStructureToken(Token.EndLoop); - - var jumpFalseIndex = AddCommand(OperationCode.JmpFalse, 0); - NextToken(); - bool savedTryFlag = SetTryBlockFlag(false); - BuildCodeBatch(); - SetTryBlockFlag(savedTryFlag); - PopStructureToken(); - - if (_lastExtractedLexem.Token == Token.EndLoop) - AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); - - AddCommand(OperationCode.Jmp, conditionIndex); - + } + + private void BuildWhileStatement() + { + NextToken(); + var conditionIndex = _module.Code.Count; + var loopRecord = NestedLoopInfo.New(); + loopRecord.startPoint = conditionIndex; + _nestedLoops.Push(loopRecord); + BuildExpression(Token.Loop); + PushStructureToken(Token.EndLoop); + + var jumpFalseIndex = AddCommand(OperationCode.JmpFalse, 0); + NextToken(); + bool savedTryFlag = SetTryBlockFlag(false); + BuildCodeBatch(); + SetTryBlockFlag(savedTryFlag); + PopStructureToken(); + + if (_lastExtractedLexem.Token == Token.EndLoop) + { + AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber, isExtraCode: true); + } + + AddCommand(OperationCode.Jmp, conditionIndex); + var endLoop = AddCommand(OperationCode.Nop, 0); - _module.Code[jumpFalseIndex] = new Command() - { + _module.Code[jumpFalseIndex] = new Command() { Code = OperationCode.JmpFalse, Argument = endLoop }; @@ -931,7 +936,7 @@ private void BuildTryExceptStatement() if (StringComparer.OrdinalIgnoreCase.Compare(_lastExtractedLexem.Content, "Exception") == 0) SystemLogger.Write("WARNING! BREAKING CHANGE: Keyword 'Exception' is not supported anymore. Consider using 'Except'"); - var beginHandler = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + var beginHandler = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber, isExtraCode: true); CorrectCommandArgument(beginTryIndex, beginHandler); @@ -940,7 +945,7 @@ private void BuildTryExceptStatement() BuildCodeBatch(); PopStructureToken(); - var endIndex = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber); + var endIndex = AddCommand(OperationCode.LineNum, _lastExtractedLexem.LineNumber, isExtraCode: true); AddCommand(OperationCode.EndTry, 0); CorrectCommandArgument(jmpIndex, endIndex); @@ -1786,11 +1791,11 @@ private Token[] PopStructureToken() private int AddCommand(OperationCode code, int arg, bool isExtraCode = false) { - if (isExtraCode && !ProduceExtraCode) - return -1; - - var addr = _module.Code.Count; - _module.Code.Add(new Command() { Code = code, Argument = arg }); + var addr = _module.Code.Count; + if (!isExtraCode || ProduceExtraCode) + { + _module.Code.Add(new Command() { Code = code, Argument = arg }); + } return addr; } From d752da21d8081b28412d43692f8cbea7e3728437 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Sun, 15 Jan 2017 15:16:46 +0400 Subject: [PATCH 39/63] =?UTF-8?q?Fixes=20#304:=20=D0=BD=D0=BE=D1=87=D0=BD?= =?UTF-8?q?=D1=8B=D0=B5=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B8=20=D0=B2=20?= =?UTF-8?q?AppVeyor.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AppVeyor: добавлена сборка и публикация nuget-пакетов в хранилище nuget от AppVeyor. --- appveyor.yml | 11 ++++++++++- src/GlobalAssemblyInfo.cs | 6 +++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 69602089f..d3e01f386 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,8 +1,16 @@ -version: 1.0.15.{build} +version: 1.0.16-alpha{build} pull_requests: do_not_increment_build_number: true configuration: Release platform: x86 +assembly_info: + patch: true + assembly_version: '{version}' + assembly_file_version: '{version}' + assembly_informational_version: '{version}' +nuget: + project_feed: true + disable_publish_on_pr: true init: - ps: Set-WinSystemLocale ru-RU - ps: Start-Sleep -s 5 @@ -13,6 +21,7 @@ before_build: - nuget restore src/1Script_Mono.sln build: project: src/1Script_Mono.sln + publish_nuget: true verbosity: minimal test_script: - cmd: appveyor-runtests.cmd diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs index d797d0482..2f65028f5 100644 --- a/src/GlobalAssemblyInfo.cs +++ b/src/GlobalAssemblyInfo.cs @@ -17,9 +17,9 @@ This Source Code Form is subject to the terms of the [assembly: System.Reflection.AssemblyCompany("BeaverSoft")] [assembly: System.Reflection.AssemblyCopyright("Copyright (c) 2016 EvilBeaver")] [assembly: System.Reflection.AssemblyConfiguration("Commit 2a614c0")] -[assembly: System.Reflection.AssemblyVersion("1.0.15.0")] -[assembly: System.Reflection.AssemblyFileVersion("1.0.15.0")] -[assembly: System.Reflection.AssemblyInformationalVersion("1.0.15.0")] +[assembly: System.Reflection.AssemblyVersion("1.0.16.0")] +[assembly: System.Reflection.AssemblyFileVersion("1.0.16.0")] +[assembly: System.Reflection.AssemblyInformationalVersion("1.0.16.0")] From 9655edb243a8917435da7ee861d14975cc6378e3 Mon Sep 17 00:00:00 2001 From: Sergey Batanov Date: Wed, 18 Jan 2017 12:28:01 +0300 Subject: [PATCH 40/63] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B2=20XML-=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=86=D0=B8=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine.HostedScript/HostedScriptEngine.cs | 1 - .../Library/Binary/FileStreamContext.cs | 2 +- src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs | 2 +- .../Library/Binary/MemoryStreamContext.cs | 2 +- src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs | 2 +- src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs | 2 +- .../Library/Json/JSONWriterSettings.cs | 4 ++-- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index f38006a3f..5761459ed 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -231,6 +231,5 @@ public void Finalize() { _codeStat?.OutputCodeStat(); } - } } diff --git a/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs b/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs index 6f69b3548..6d06823f5 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs @@ -137,7 +137,7 @@ public void CopyTo(IValue targetStream, int bufferSize = 0) /// /// /// Количество байтов, на которое нужно передвинуть позицию в потоке. - /// + /// /// Начальная позиция, от которой отсчитывается смещение. /// /// Числовым типом может быть представлено любое десятичное число. Над данными числового типа определены основные арифметические операции: сложение, вычитание, умножение и деление. Максимально допустимая разрядность числа 38 знаков. diff --git a/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs b/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs index 087514870..067e0d8c9 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs @@ -125,7 +125,7 @@ public void CopyTo(IValue targetStream, int bufferSize = 0) /// /// /// Количество байтов, на которое нужно передвинуть позицию в потоке. - /// + /// /// Начальная позиция, от которой отсчитывается смещение. /// /// Числовым типом может быть представлено любое десятичное число. Над данными числового типа определены основные арифметические операции: сложение, вычитание, умножение и деление. Максимально допустимая разрядность числа 38 знаков. diff --git a/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs b/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs index 9e1a45309..48f2c6908 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs @@ -156,7 +156,7 @@ public void CopyTo(IValue targetStream, int bufferSize = 0) /// /// /// Количество байтов, на которое нужно передвинуть позицию в потоке. - /// + /// /// Начальная позиция, от которой отсчитывается смещение. /// /// Числовым типом может быть представлено любое десятичное число. Над данными числового типа определены основные арифметические операции: сложение, вычитание, умножение и деление. Максимально допустимая разрядность числа 38 знаков. diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs index e20a64b47..c15719682 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs @@ -217,7 +217,7 @@ public void Close() /// /// Имя файла, содержащего текст JSON. /// - /// Позволяет задать кодировку входного файла. + /// Позволяет задать кодировку входного файла. [ContextMethod("ОткрытьФайл", "OpenFile")] public void OpenFile(string JSONFileName, IValue Encoding = null) { diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs index 95b2d208d..547cb1749 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs @@ -368,7 +368,7 @@ public void WriteStartObject() /// Определяет, будет ли добавлен маркер порядка байт (BOM) к результирующему файлу JSON. /// Внимание. Стандарт RFC7159 настоятельно рекомендует не добавлять маркер порядка байт (BOM) к документу JSON . /// Значение по умолчанию: Ложь. - /// + /// /// Параметры, используемые при открытии файла для настройки записи в формате JSON. [ContextMethod("ОткрытьФайл", "OpenFile")] public void OpenFile(string fileName, string encoding = null, IValue addBOM = null, IValue settings = null) diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs index 90c49d2f1..8713c3f0a 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs @@ -64,13 +64,13 @@ public JSONWriterSettings(IValue NewLines = null, string PaddingSymbols = null, /// Определяет используемый способ экранирования (замены) символов при записи данных JSON. /// Значение по умолчанию: Нет. /// - /// Определяет, будут ли при записи экранироваться символы "<" и ">". + /// Определяет, будут ли при записи экранироваться символы '<' и '>'. /// Значение по умолчанию: Ложь. /// /// Определяет, будут ли экранироваться разделители строк - U+2028 (line-separator) и U+2029 (page-separator). /// Значение по умолчанию: Истина. /// - /// Определяет, будет ли при записи экранироваться символ амперсанда "&". + /// Определяет, будет ли при записи экранироваться символ амперсанда '&'. /// Значение по умолчанию: Ложь. /// /// Определяет, будут ли экранироваться одинарные кавычки. From 42d2a631ceebb1dc733802d1125dd814f09966e1 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 12 Feb 2017 18:11:58 +0300 Subject: [PATCH 41/63] =?UTF-8?q?=D0=9F=D1=80=D0=B8=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=20Ordinal=20=D0=B2=20=D0=A1=D1=82=D1=80=D0=9D?= =?UTF-8?q?=D0=B0=D0=B9=D1=82=D0=B8,=20=D0=BF=D0=B5=D1=80=D0=B5=D1=87?= =?UTF-8?q?=D0=B8=D1=81=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=9D=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=D0=9F=D0=BE?= =?UTF-8?q?=D0=B8=D1=81=D0=BA=D0=B0=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=D0=BE=20=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D1=8B=D0=B5=20=D0=BF=D0=B5=D1=80=D0=B5=D1=87=D0=B8?= =?UTF-8?q?=D1=81=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/StringOperations.cs | 55 +++++-------------- 1 file changed, 13 insertions(+), 42 deletions(-) diff --git a/src/ScriptEngine.HostedScript/Library/StringOperations.cs b/src/ScriptEngine.HostedScript/Library/StringOperations.cs index 0308d998f..7f43c1368 100644 --- a/src/ScriptEngine.HostedScript/Library/StringOperations.cs +++ b/src/ScriptEngine.HostedScript/Library/StringOperations.cs @@ -152,16 +152,13 @@ public int StrCompare(string first, string second) /// Указывает номер вхождения искомой подстроки в исходной строке /// Позицию искомой строки в исходной строке. Возвращает 0, если подстрока не найдена. [ContextMethod("СтрНайти", "StrFind")] - public int StrFind(string haystack, string needle, SelfAwareEnumValue direction = null, int startPos = 0, int occurance = 0) + public int StrFind(string haystack, string needle, SearchDirection direction = SearchDirection.FromBegin, int startPos = 0, int occurance = 0) { int len = haystack.Length; if (len == 0 || needle.Length == 0) return 0; - if (direction == null) - direction = GlobalsManager.GetEnum().FromBegin as SelfAwareEnumValue; - - bool fromBegin = direction == GlobalsManager.GetEnum().FromBegin; + bool fromBegin = direction == SearchDirection.FromBegin; if(startPos == 0) { @@ -182,7 +179,7 @@ public int StrFind(string haystack, string needle, SelfAwareEnumValue= 0) { - index = haystack.IndexOf(needle, startIndex); + index = haystack.IndexOf(needle, startIndex, StringComparison.Ordinal); if (index >= 0) { startIndex = index + 1; @@ -197,7 +194,7 @@ public int StrFind(string haystack, string needle, SelfAwareEnumValue= 0) { - index = haystack.LastIndexOf(needle, startIndex); + index = haystack.LastIndexOf(needle, startIndex, StringComparison.Ordinal); if (index >= 0) { startIndex = index - 1; @@ -293,7 +290,7 @@ private IValue CallStrTemplate(IValue[] arguments) var re = new System.Text.RegularExpressions.Regex(@"(%%)|(%\d+)|(%\D)"); int matchCount = 0; - int passedArgsCount = arguments.Skip(1).Where(x => x != null && x.DataType != DataType.Undefined).Count(); + int passedArgsCount = arguments.Skip(1).Count(x => x != null && x.DataType != DataType.Undefined); var result = re.Replace(srcFormat, (m) => { if (m.Groups[1].Success) @@ -329,40 +326,14 @@ public static IAttachableContext CreateInstance() } - - [SystemEnum("НаправлениеПоиска", "SearchDirection")] - public class SearchDirectionEnum : EnumerationContext + [EnumerationType("НаправлениеПоиска", "SearchDirection")] + public enum SearchDirection { - const string FROM_BEGIN = "СНачала"; - const string FROM_END = "СКонца"; - - public SearchDirectionEnum(TypeDescriptor typeRepresentation, TypeDescriptor valuesType) - : base(typeRepresentation, valuesType) - { - - } - - [EnumValue(FROM_BEGIN, "FromBegin")] - public EnumerationValue FromBegin - { - get - { - return this[FROM_BEGIN]; - } - } - - [EnumValue(FROM_END, "FromEnd")] - public EnumerationValue FromEnd - { - get - { - return this[FROM_END]; - } - } - - public static SearchDirectionEnum CreateInstance() - { - return EnumContextHelper.CreateEnumInstance((t, v) => new SearchDirectionEnum(t, v)); - } + [EnumItem("СНачала")] + FromBegin, + [EnumItem("СКонца")] + FromEnd } + + } From 0f30d096e3802fb3db4d597b45b778051a406ab8 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 12 Feb 2017 18:18:57 +0300 Subject: [PATCH 42/63] =?UTF-8?q?fixed=20#401.=20=D0=9F=D1=80=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B5=D0=BD=20Ordinal=20=D0=B2=20=D0=9D=D0=B0?= =?UTF-8?q?=D0=B9=D1=82=D0=B8/=D0=A1=D1=82=D1=80=D0=9D=D0=B0=D0=B9=D1=82?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine/Machine/MachineInstance.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index 8ae8d5502..23a9e8af7 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -1620,7 +1620,7 @@ private void StrPos(int arg) var needle = _operationStack.Pop().AsString(); var haystack = _operationStack.Pop().AsString(); - var result = haystack.IndexOf(needle) + 1; + var result = haystack.IndexOf(needle, StringComparison.Ordinal) + 1; _operationStack.Push(ValueFactory.Create(result)); NextInstruction(); } From fcc95fb5c36a3d345a1b10e9131bf3d2eb0b2fcd Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 12 Feb 2017 18:33:56 +0300 Subject: [PATCH 43/63] =?UTF-8?q?fixed=20#400.=20=D0=92=20=D1=81=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D0=B0=D0=B5=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8?= =?UTF-8?q?=20=D1=86=D0=B8=D0=BA=D0=BB=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8?= =?UTF-8?q?=D1=85=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B5=D0=B9=20=D0=B2=D1=8B=D0=B4=D0=B0=D0=B5=D1=82=D1=81?= =?UTF-8?q?=D1=8F=20=D1=81=D0=BF=D0=B8=D1=81=D0=BE=D0=BA=20=D0=BE=D0=B1?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=D0=B0=20=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B6?= =?UTF-8?q?=D0=B0=D0=B5=D0=BC=D1=8B=D1=85=20=D0=B1=D0=B8=D0=B1=D0=BB=D0=B8?= =?UTF-8?q?=D0=BE=D1=82=D0=B5=D0=BA.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LibraryResolver.cs | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/ScriptEngine.HostedScript/LibraryResolver.cs b/src/ScriptEngine.HostedScript/LibraryResolver.cs index 2c12ae4fa..699cca2bc 100644 --- a/src/ScriptEngine.HostedScript/LibraryResolver.cs +++ b/src/ScriptEngine.HostedScript/LibraryResolver.cs @@ -242,9 +242,13 @@ private bool LoadLibraryInternal(string libraryPath) if(existedLib != null) { if (existedLib.state == ProcessingState.Discovered) - throw new RuntimeException(String.Format("Ошибка загрузки библиотеки {0}. Обнаружены циклические зависимости", id)); - else - return true; + { + string libStack = listToStringStack(_libs, id); + throw new RuntimeException($"Ошибка загрузки библиотеки {id}. Обнаружены циклические зависимости.\n" + + $"{libStack}"); + } + + return true; } var newLib = new Library() { id = id, state = ProcessingState.Discovered }; @@ -270,6 +274,25 @@ private bool LoadLibraryInternal(string libraryPath) return hasFiles; } + private string listToStringStack(List libs, string stopToken) + { + var builder = new StringBuilder(); + string offset = ""; + foreach (var library in libs) + { + builder.Append(offset); + builder.Append("-> "); + builder.Append(library.id); + offset += " "; + if (library.id == stopToken) + { + break; + } + } + + return builder.ToString(); + } + private string GetLibraryId(string libraryPath) { return Path.GetFullPath(libraryPath); From d49d1835b72c65ca173ea2d2825257d40092f3f9 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 12 Feb 2017 18:37:38 +0300 Subject: [PATCH 44/63] fixed #373 --- src/ScriptEngine/Machine/RuntimeExceptions.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/ScriptEngine/Machine/RuntimeExceptions.cs b/src/ScriptEngine/Machine/RuntimeExceptions.cs index e12eb74ee..c4a958726 100644 --- a/src/ScriptEngine/Machine/RuntimeExceptions.cs +++ b/src/ScriptEngine/Machine/RuntimeExceptions.cs @@ -96,6 +96,11 @@ public static RuntimeException InvalidArgumentValue() return new RuntimeException("Неверное значение аргумента"); } + public static RuntimeException InvalidArgumentValue(object value) + { + return new RuntimeException("Неверное значение аргумента {"+value.ToString()+"}"); + } + public static RuntimeException ComparisonNotSupportedException() { return new RuntimeException("Сравнение на больше/меньше для данного типа не поддерживается"); From c4be395688527918efbe0d9e5f70ad84bd96fce5 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 12 Feb 2017 21:35:35 +0300 Subject: [PATCH 45/63] =?UTF-8?q?=D0=9E=D0=B1=D0=B5=D1=80=D1=82=D0=BA?= =?UTF-8?q?=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=B0=D1=81=D0=B8=D0=BD=D1=85?= =?UTF-8?q?=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=87=D1=82=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D0=BF=D0=BE=D1=82=D0=BE=D0=BA=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/ProcessContext.cs | 17 +- .../Library/ProcessOutputWrapper.cs | 224 ++++++++++++++++++ .../Library/StdTextReadStream.cs | 6 +- .../ScriptEngine.HostedScript.csproj | 5 +- 4 files changed, 242 insertions(+), 10 deletions(-) create mode 100644 src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs diff --git a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs index 719e172db..0db1f5b58 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs @@ -58,9 +58,13 @@ public StdTextReadStream StdOut { get { - if(_stdOutContext == null) - _stdOutContext = new StdTextReadStream(_p.StandardOutput); - + if (_stdOutContext == null) + { + var stream = new ProcessOutputWrapper(_p, ProcessOutputWrapper.OutputVariant.Stdout); + stream.StartReading(); + + _stdOutContext = new StdTextReadStream(stream); + } return _stdOutContext; } } @@ -74,7 +78,12 @@ public StdTextReadStream StdErr get { if (_stdErrContext == null) - _stdErrContext = new StdTextReadStream(_p.StandardError); + { + var stream = new ProcessOutputWrapper(_p, ProcessOutputWrapper.OutputVariant.Stderr); + stream.StartReading(); + + _stdErrContext = new StdTextReadStream(stream); + } return _stdErrContext; } } diff --git a/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs b/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs new file mode 100644 index 000000000..0ab46a7b6 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; + +using sys = System.Diagnostics; + +namespace ScriptEngine.HostedScript.Library +{ + class ProcessOutputWrapper : TextReader + { + private sys.Process _process; + private OutputVariant _variant; + private StringBuilder _buffer = new StringBuilder(4096); + private ReaderWriterLockSlim _locker; + + private int _bufferIndex = 0; + + private bool AlreadyReading { get; set; } + + private Encoding Encoding { get; set; } + + public enum OutputVariant + { + Stdout, + Stderr + } + + public ProcessOutputWrapper(sys.Process process, OutputVariant variant) + { + _process = process; + _variant = variant; + _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); + } + + public void StartReading() + { + if (AlreadyReading) + return; + + if (_variant == OutputVariant.Stdout) + { + Encoding = _process.StartInfo.StandardOutputEncoding; + _process.BeginOutputReadLine(); + _process.OutputDataReceived += StreamDataReceived; + } + else + { + Encoding = _process.StartInfo.StandardErrorEncoding; + _process.BeginErrorReadLine(); + _process.ErrorDataReceived += StreamDataReceived; + } + + AlreadyReading = true; + } + + private void StopReading() + { + if (_variant == OutputVariant.Stdout) + { + _process.OutputDataReceived -= StreamDataReceived; + } + else + { + _process.ErrorDataReceived -= StreamDataReceived; + } + } + + private void StreamDataReceived(object sender, sys.DataReceivedEventArgs e) + { + try + { + _locker.EnterWriteLock(); + { + if (e.Data != null) + { + if (_buffer.Length != 0) + _buffer.Append(System.Environment.NewLine); + + _buffer.Append(e.Data); + } + } + } + finally + { + if(_locker.IsWriteLockHeld) // При else бросит правильное исключение, из-за которого не захватил блокировку + _locker.ExitWriteLock(); + } + } + + public override int Peek() + { + try + { + _locker.EnterReadLock(); + if (_bufferIndex >= _buffer.Length) + return -1; // no data + + return _buffer[_bufferIndex]; + } + finally + { + if (_locker.IsReadLockHeld) // При else бросит правильное исключение, из-за которого не захватил блокировку + _locker.ExitReadLock(); + } + + } + + public override int Read() + { + try + { + _locker.EnterReadLock(); + return ReadInternal(); + } + finally + { + if (_locker.IsReadLockHeld) + _locker.ExitReadLock(); + } + } + + private int ReadInternal() + { + if (_bufferIndex < _buffer.Length) + return _buffer[_bufferIndex++]; + + return -1; + } + + public override int Read(char[] destBuffer, int index, int count) + { + if (destBuffer == null) + throw new ArgumentNullException(nameof(destBuffer)); + if (index < 0) + throw new ArgumentOutOfRangeException(nameof(index), "Index is below zero"); + if (count < 0) + throw new ArgumentOutOfRangeException(nameof(count), "Count is below zero"); + if (destBuffer.Length - index < count) + throw new ArgumentException("Invalid offset"); + + try + { + _locker.EnterReadLock(); + int n = 0; + do + { + int ch = ReadInternal(); + if (ch == -1) break; + + destBuffer[index + n++] = (char) ch; + } while (n < count); + + return n; + } + finally + { + if (_locker.IsReadLockHeld) + _locker.ExitReadLock(); + } + } + + public override string ReadLine() + { + try + { + _locker.EnterReadLock(); + var sb = new StringBuilder(); + while (true) + { + int ch = ReadInternal(); + if (ch == -1) break; + if (ch == '\r' || ch == '\n') + { + if (ch == '\r' && Peek() == '\n') Read(); + return sb.ToString(); + } + sb.Append((char)ch); + } + if (sb.Length > 0) return sb.ToString(); + return null; + } + finally + { + if (_locker.IsReadLockHeld) + _locker.ExitReadLock(); + } + } + + public override string ReadToEnd() + { + try + { + _locker.EnterReadLock(); + string data = base.ReadToEnd(); + ResetBuffer(); + return data; + } + finally + { + if (_locker.IsReadLockHeld) + _locker.ExitReadLock(); + } + } + + private void ResetBuffer() + { + _buffer.Clear(); + _bufferIndex = 0; + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + StopReading(); + } + + base.Dispose(disposing); + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs b/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs index e398e4b28..a732efee5 100644 --- a/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs +++ b/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs @@ -20,9 +20,9 @@ namespace ScriptEngine.HostedScript.Library [ContextClass("ПотокВыводаТекста","TextOutputStream")] public class StdTextReadStream : AutoContext, IDisposable { - private readonly StreamReader _reader; + private readonly TextReader _reader; - public StdTextReadStream(StreamReader source) + public StdTextReadStream(TextReader source) { _reader = source; } @@ -40,7 +40,7 @@ public bool HasData { get { - return !_reader.EndOfStream; + return _reader.Peek() != -1; } } diff --git a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj index be382856b..2485e4c26 100644 --- a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj +++ b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj @@ -146,6 +146,7 @@ + @@ -224,9 +225,7 @@ - - - + From 65f0c46b25c4f1a3e831ac8133435d3d3510bc02 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 12 Feb 2017 21:55:35 +0300 Subject: [PATCH 46/63] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BE=D0=B6=D0=B8=D0=B4=D0=B0=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=84=D0=B8=D0=BD=D0=B0=D0=BB=D0=B8=D0=B7=D0=B8?= =?UTF-8?q?=D1=80=D1=83=D1=8E=D1=89=D0=B5=D0=BC=20=D1=87=D1=82=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/ProcessOutputWrapper.cs | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs b/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs index 0ab46a7b6..0ef56c7f3 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs @@ -16,6 +16,8 @@ class ProcessOutputWrapper : TextReader private StringBuilder _buffer = new StringBuilder(4096); private ReaderWriterLockSlim _locker; + private ManualResetEventSlim _finalWriteEvent = new ManualResetEventSlim(); + private int _bufferIndex = 0; private bool AlreadyReading { get; set; } @@ -81,6 +83,10 @@ private void StreamDataReceived(object sender, sys.DataReceivedEventArgs e) _buffer.Append(e.Data); } + else + { + _finalWriteEvent.Set(); + } } } finally @@ -94,7 +100,7 @@ public override int Peek() { try { - _locker.EnterReadLock(); + EnterReadLock(); if (_bufferIndex >= _buffer.Length) return -1; // no data @@ -112,7 +118,7 @@ public override int Read() { try { - _locker.EnterReadLock(); + EnterReadLock(); return ReadInternal(); } finally @@ -143,7 +149,7 @@ public override int Read(char[] destBuffer, int index, int count) try { - _locker.EnterReadLock(); + EnterReadLock(); int n = 0; do { @@ -166,7 +172,7 @@ public override string ReadLine() { try { - _locker.EnterReadLock(); + EnterReadLock(); var sb = new StringBuilder(); while (true) { @@ -193,7 +199,7 @@ public override string ReadToEnd() { try { - _locker.EnterReadLock(); + EnterReadLock(); string data = base.ReadToEnd(); ResetBuffer(); return data; @@ -211,6 +217,16 @@ private void ResetBuffer() _bufferIndex = 0; } + private void EnterReadLock() + { + if (_process.HasExited) + { + _finalWriteEvent.Wait(); + } + + _locker.EnterReadLock(); + } + protected override void Dispose(bool disposing) { if (disposing) From 54a1e97b8d5f6a52a0ca713fcb86c5149fa1f95b Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 12 Feb 2017 22:29:06 +0300 Subject: [PATCH 47/63] =?UTF-8?q?=D0=9E=D1=82=D1=80=D0=B0=D0=B7=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BD=D0=BE=D0=B2=D0=BE=D0=B5=20=D0=BF=D0=BE=D0=B2?= =?UTF-8?q?=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2=20=D1=82=D0=B5?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D1=85.=20see=20#402?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/process.os | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/process.os b/tests/process.os index fd120827d..805f244de 100644 --- a/tests/process.os +++ b/tests/process.os @@ -37,6 +37,7 @@ Процесс = СоздатьПроцесс("""" + Путь + """",,Истина); Процесс.Запустить(); Поток = Процесс.ПотокВывода; + Процесс.ОжидатьЗавершения(); Стр = НормализоватьПереводыСтрок(Поток.Прочитать()); @@ -60,6 +61,8 @@ КонецЦикла; КонецЦикла; + Стр = СокрП(Стр); + юТест.ПроверитьРавенство(ШтатныйВыводOscript(), НормализоватьПереводыСтрок(Стр)); КонецПроцедуры @@ -81,13 +84,13 @@ Процесс.ПотокВвода.Закрыть(); Консоль.КодировкаВходногоПотока = КодировкаПоУмолчанию; + Процесс.ОжидатьЗавершения(); Вывод = Процесс.ПотокВывода.Прочитать(); Эталон = НормализоватьПереводыСтрок("1 |2 - |3 - |"); + |3"); юТест.ПроверитьРавенство(Эталон, НормализоватьПереводыСтрок(Вывод)); КонецПроцедуры @@ -136,8 +139,7 @@ | Builds a standalone executable module based on script specified | |IV. Run as CGI application: oscript.exe -cgi [script arguments..] - | Runs as CGI application under HTTP-server (Apache/Nginx/IIS/etc...) - |"; + | Runs as CGI application under HTTP-server (Apache/Nginx/IIS/etc...)"; Возврат НормализоватьПереводыСтрок(Текст); From 5ddc0d5396702952ab751509f019656d91d7b5c6 Mon Sep 17 00:00:00 2001 From: "Alexander I. Borisov" Date: Fri, 17 Feb 2017 14:04:15 +0300 Subject: [PATCH 48/63] Update CODESTYLE.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Все-таки проект на C#, а не на C. --- CODESTYLE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODESTYLE.md b/CODESTYLE.md index e7a420d85..d7471dac7 100644 --- a/CODESTYLE.md +++ b/CODESTYLE.md @@ -1,4 +1,4 @@ -# Требования к исходному коду на языке C# +# Требования к исходному коду на языке C# # ## Общие правила @@ -166,4 +166,4 @@ if (!canRead) 2. "Рефакторинг. Улучшение существующего кода", М. Фаулер 3. "Инфраструктура программных проектов", К. Цвалина, Б. Адамс - \ No newline at end of file + From ddf95adcdaa272bafd188a2689011c89e1c98edd Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 19 Feb 2017 18:38:50 +0300 Subject: [PATCH 49/63] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81:=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B1=D1=8B=D1=82=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine.HostedScript/LibraryResolver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScriptEngine.HostedScript/LibraryResolver.cs b/src/ScriptEngine.HostedScript/LibraryResolver.cs index 699cca2bc..1750556f8 100644 --- a/src/ScriptEngine.HostedScript/LibraryResolver.cs +++ b/src/ScriptEngine.HostedScript/LibraryResolver.cs @@ -282,7 +282,7 @@ private string listToStringStack(List libs, string stopToken) { builder.Append(offset); builder.Append("-> "); - builder.Append(library.id); + builder.AppendLine(library.id); offset += " "; if (library.id == stopToken) { From 68b3bfcd3d320aa3b77f4896ed45463774dcdc3d Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Mon, 20 Feb 2017 01:55:20 +0300 Subject: [PATCH 50/63] =?UTF-8?q?=D0=94=D0=BE=D0=BA=D1=83=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=D0=BC=D0=B5=D1=80=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=BE=D0=B9=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B8=20=D1=86=D0=B8=D0=BA=D0=BB=D0=B0=20=D0=BE?= =?UTF-8?q?=D0=B6=D0=B8=D0=B4=D0=B0=D0=BD=D0=B8=D1=8F=20=D0=B7=D0=B0=D0=B2?= =?UTF-8?q?=D0=B5=D1=80=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D1=86=D0=B5=D1=81=D1=81=D0=B0=20#402?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Library/ProcessContext.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs index 0db1f5b58..fb716f98e 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs @@ -52,6 +52,7 @@ public IValue OutputEncoding /// /// ПотокВыводаТекста. Стандартный поток вывода (stdout) + /// в методе "Завершен" смотрите пример правильной обработки цикла ожидания завершения процесса: /// [ContextProperty("ПотокВывода", "StdOut")] public StdTextReadStream StdOut @@ -71,6 +72,7 @@ public StdTextReadStream StdOut /// /// ПотокВыводаТекста. Стандартный поток вывода ошибок (stderr) + /// в методе "Завершен" смотрите пример правильной обработки цикла ожидания завершения процесса: /// [ContextProperty("ПотокОшибок", "StdErr")] public StdTextReadStream StdErr @@ -104,6 +106,7 @@ public StdTextWriteStream StdIn /// /// Запустить процесс на выполнение. + /// в методе "Завершен" смотрите пример правильной обработки цикла ожидания завершения процесса: /// [ContextMethod("Запустить", "Start")] public void Start() @@ -113,6 +116,24 @@ public void Start() /// /// Флаг указывает, что процесс завершен (или нет) + /// + /// Пример правильной обработки цикла ожидания завершения процесса: + /// + /// Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные ИЛИ Процесс.ПотокОшибок.ЕстьДанные Цикл + /// Если ПериодОпросаВМиллисекундах <> 0 Тогда + /// Приостановить(ПериодОпросаВМиллисекундах); + /// КонецЕсли; + /// + /// ОчереднаяСтрокаВывода = Процесс.ПотокВывода.Прочитать(); + /// ОчереднаяСтрокаОшибок = Процесс.ПотокОшибок.Прочитать(); + /// Если Не ПустаяСтрока(ОчереднаяСтрокаВывода) Тогда + /// Сообщить(ОчереднаяСтрокаВывода, СтатусСообщения.Информация); + /// КонецЕсли; + /// + /// Если Не ПустаяСтрока(ОчереднаяСтрокаОшибок) Тогда + /// Сообщить(ОчереднаяСтрокаОшибок, СтатусСообщения.Важное); + /// КонецЕсли; + /// КонецЦикла; /// [ContextProperty("Завершен","HasExited")] public bool HasExited From c5655170660f75edb09b06cdffc4f30f4f23e0a9 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Mon, 20 Feb 2017 15:17:30 +0300 Subject: [PATCH 51/63] =?UTF-8?q?=D0=97=D0=B0=D0=BB=D0=B5=D1=87=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BA=D0=BE=D1=81=D1=82=D1=8B=D0=BB=D0=B5=D0=BC=20?= =?UTF-8?q?=D0=BF=D0=B0=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20-check.=20see=20#4?= =?UTF-8?q?07?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HostedScriptEngine.cs | 2 +- src/oscript/CheckSyntaxBehavior.cs | 1 + src/oscript/SimpleConsoleHost.cs | 34 +++++++++++++++++++ src/oscript/oscript.csproj | 1 + 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/oscript/SimpleConsoleHost.cs diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index f38006a3f..0f6dec565 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -207,7 +207,7 @@ public Process CreateProcess(IHostApplication host, ScriptModuleHandle moduleHan return InitProcess(host, ref module); } - private void SetGlobalEnvironment(IHostApplication host, ICodeSource src) + public void SetGlobalEnvironment(IHostApplication host, ICodeSource src) { _globalCtx.ApplicationHost = host; _globalCtx.CodeSource = src; diff --git a/src/oscript/CheckSyntaxBehavior.cs b/src/oscript/CheckSyntaxBehavior.cs index 88a0d2318..eacc45231 100644 --- a/src/oscript/CheckSyntaxBehavior.cs +++ b/src/oscript/CheckSyntaxBehavior.cs @@ -40,6 +40,7 @@ public override int Execute() ScriptFileHelper.OnBeforeScriptRead(hostedScript); var source = hostedScript.Loader.FromFile(_path); + hostedScript.SetGlobalEnvironment(new SimpleConsoleHost(), source); try { diff --git a/src/oscript/SimpleConsoleHost.cs b/src/oscript/SimpleConsoleHost.cs new file mode 100644 index 000000000..d44dc377e --- /dev/null +++ b/src/oscript/SimpleConsoleHost.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using ScriptEngine.HostedScript; +using ScriptEngine.HostedScript.Library; + +namespace oscript +{ + internal class SimpleConsoleHost : IHostApplication + { + + public void Echo(string text, MessageStatusEnum status = MessageStatusEnum.Ordinary) + { + ConsoleHostImpl.Echo(text, status); + } + + public void ShowExceptionInfo(Exception exc) + { + ConsoleHostImpl.ShowExceptionInfo(exc); + } + + public bool InputString(out string result, int maxLen) + { + return ConsoleHostImpl.InputString(out result, maxLen); + } + + public string[] GetCommandLineArguments() + { + return null; + } + } +} diff --git a/src/oscript/oscript.csproj b/src/oscript/oscript.csproj index 53ef2012e..24e972fad 100644 --- a/src/oscript/oscript.csproj +++ b/src/oscript/oscript.csproj @@ -105,6 +105,7 @@ + From 721b6ba6d98c10234062831730e5d5d9c09af7b3 Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Tue, 21 Feb 2017 09:20:02 +0300 Subject: [PATCH 52/63] =?UTF-8?q?=D0=92=D1=8B=D0=B4=D0=B5=D0=BB=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D0=BF=D0=B5=D1=86.=D1=82=D0=B5=D0=B3=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BB=D1=8F=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=86=D0=B8=D0=B8=20=20#402?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine.HostedScript/Library/ProcessContext.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs index fb716f98e..6048b26c3 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs @@ -116,7 +116,9 @@ public void Start() /// /// Флаг указывает, что процесс завершен (или нет) + /// /// + /// /// Пример правильной обработки цикла ожидания завершения процесса: /// /// Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные ИЛИ Процесс.ПотокОшибок.ЕстьДанные Цикл @@ -134,7 +136,7 @@ public void Start() /// Сообщить(ОчереднаяСтрокаОшибок, СтатусСообщения.Важное); /// КонецЕсли; /// КонецЦикла; - /// + /// [ContextProperty("Завершен","HasExited")] public bool HasExited { From c3365b905df1f115a43fad36e417efca0ac8e8ee Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Tue, 21 Feb 2017 10:03:22 +0300 Subject: [PATCH 53/63] =?UTF-8?q?=D0=BE=D0=BF=D0=B8=D1=81=D0=B0=D0=BB=20"?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D1=8C=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D1=8C"=20#402?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine.HostedScript/Library/ProcessContext.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs index 6048b26c3..7816ebe1a 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs @@ -120,6 +120,8 @@ public void Start() /// /// /// Пример правильной обработки цикла ожидания завершения процесса: + /// Процесс не завершается, пока поток stderr открыт для чтения + /// Он висит в процессах и ждет, пока его освободят от текста в stderr /// /// Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные ИЛИ Процесс.ПотокОшибок.ЕстьДанные Цикл /// Если ПериодОпросаВМиллисекундах <> 0 Тогда From ebb254ed26f4affe3bc9a395f78b77adcb2ff54c Mon Sep 17 00:00:00 2001 From: Artur Ayukhanov Date: Thu, 23 Feb 2017 12:10:19 +0300 Subject: [PATCH 54/63] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D1=84=D0=BE=D1=80=D0=BC=D1=83=D0=BB=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BA=D0=B8=20=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB?= =?UTF-8?q?=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D0=B8=20=D0=B7=D0=B0=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BF=D1=80=D0=BE=D1=86?= =?UTF-8?q?=D0=B5=D1=81=D1=81=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /// Процесс не завершается, пока любоой из потоков (stdout, stderr) открыт для чтения. /// Процесс висит и ждет, пока его освободят от текста в обоих потоках. --- src/ScriptEngine.HostedScript/Library/ProcessContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs index 7816ebe1a..73238ce4c 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs @@ -120,8 +120,8 @@ public void Start() /// /// /// Пример правильной обработки цикла ожидания завершения процесса: - /// Процесс не завершается, пока поток stderr открыт для чтения - /// Он висит в процессах и ждет, пока его освободят от текста в stderr + /// Процесс не завершается, пока любоой из потоков (stdout, stderr) открыт для чтения. + /// Процесс висит и ждет, пока его освободят от текста в обоих потоках. /// /// Пока НЕ Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные ИЛИ Процесс.ПотокОшибок.ЕстьДанные Цикл /// Если ПериодОпросаВМиллисекундах <> 0 Тогда From 76a43b7ffb5c30aacccb477248a4b4ee1defdfcb Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 26 Feb 2017 18:40:32 +0300 Subject: [PATCH 55/63] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B5=D1=89=D0=B5=20=D0=BD=D0=B5=D1=81=D0=BA?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE=20=D0=BF=D1=80=D0=BE=D1=8F=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9=20#407?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/StandaloneRunner/StandaloneProcess.cs | 13 +++++++++++-- src/oscript/MakeAppBehavior.cs | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/StandaloneRunner/StandaloneProcess.cs b/src/StandaloneRunner/StandaloneProcess.cs index 00c1cb887..290d853f0 100644 --- a/src/StandaloneRunner/StandaloneProcess.cs +++ b/src/StandaloneRunner/StandaloneProcess.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.IO; using System.Runtime.Serialization.Formatters.Binary; using ScriptEngine.Environment; @@ -26,6 +27,8 @@ public int Run() var engine = new HostedScriptEngine(); engine.Initialize(); + List scriptsToLoad = new List(); + using(Stream codeStream = LocateCode()) using (var binReader = new BinaryReader(codeStream)) { @@ -42,7 +45,7 @@ public int Run() while (modulesCount-- > 0) { var userScript = reader.Read(codeStream); - engine.LoadUserScript(userScript); + scriptsToLoad.Add(userScript); } module = entry.Module; @@ -50,6 +53,12 @@ public int Run() } var src = new BinaryCodeSource(module); + engine.SetGlobalEnvironment(this, src); + foreach (var script in scriptsToLoad) + { + engine.LoadUserScript(script); + } + var process = engine.CreateProcess(this, module, src); return process.Start(); @@ -141,7 +150,7 @@ public BinaryCodeSource(ScriptModuleHandle mh) public string SourceDescription { - get { return "Compiled binary module"; } + get { return System.Reflection.Assembly.GetExecutingAssembly().Location; } } public string Code diff --git a/src/oscript/MakeAppBehavior.cs b/src/oscript/MakeAppBehavior.cs index 6762983c0..3c8ff4e2e 100644 --- a/src/oscript/MakeAppBehavior.cs +++ b/src/oscript/MakeAppBehavior.cs @@ -42,6 +42,7 @@ public override int Execute() engine.Initialize(); ScriptFileHelper.OnBeforeScriptRead(engine); var source = engine.Loader.FromFile(_codePath); + engine.SetGlobalEnvironment(new SimpleConsoleHost(), source); var compiler = engine.GetCompilerService(); var entry = compiler.CreateModule(source); From 0fb3c40ba44c7df9a31550772ec2b9cf263c068d Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 26 Feb 2017 21:15:09 +0300 Subject: [PATCH 56/63] =?UTF-8?q?=D0=9E=D1=82=D0=BA=D0=B0=D1=82=20=D0=BA?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=8B=D0=BB=D0=B5=D0=B9=20=D0=BF=D0=BE=20#40?= =?UTF-8?q?7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/StandaloneRunner/StandaloneProcess.cs | 11 +------- src/oscript/CheckSyntaxBehavior.cs | 1 - src/oscript/MakeAppBehavior.cs | 1 - src/oscript/SimpleConsoleHost.cs | 34 ----------------------- src/oscript/oscript.csproj | 1 - 5 files changed, 1 insertion(+), 47 deletions(-) delete mode 100644 src/oscript/SimpleConsoleHost.cs diff --git a/src/StandaloneRunner/StandaloneProcess.cs b/src/StandaloneRunner/StandaloneProcess.cs index 290d853f0..dfa5664c9 100644 --- a/src/StandaloneRunner/StandaloneProcess.cs +++ b/src/StandaloneRunner/StandaloneProcess.cs @@ -5,7 +5,6 @@ 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.IO; using System.Runtime.Serialization.Formatters.Binary; using ScriptEngine.Environment; @@ -27,8 +26,6 @@ public int Run() var engine = new HostedScriptEngine(); engine.Initialize(); - List scriptsToLoad = new List(); - using(Stream codeStream = LocateCode()) using (var binReader = new BinaryReader(codeStream)) { @@ -45,7 +42,7 @@ public int Run() while (modulesCount-- > 0) { var userScript = reader.Read(codeStream); - scriptsToLoad.Add(userScript); + engine.LoadUserScript(userScript); } module = entry.Module; @@ -53,12 +50,6 @@ public int Run() } var src = new BinaryCodeSource(module); - engine.SetGlobalEnvironment(this, src); - foreach (var script in scriptsToLoad) - { - engine.LoadUserScript(script); - } - var process = engine.CreateProcess(this, module, src); return process.Start(); diff --git a/src/oscript/CheckSyntaxBehavior.cs b/src/oscript/CheckSyntaxBehavior.cs index eacc45231..88a0d2318 100644 --- a/src/oscript/CheckSyntaxBehavior.cs +++ b/src/oscript/CheckSyntaxBehavior.cs @@ -40,7 +40,6 @@ public override int Execute() ScriptFileHelper.OnBeforeScriptRead(hostedScript); var source = hostedScript.Loader.FromFile(_path); - hostedScript.SetGlobalEnvironment(new SimpleConsoleHost(), source); try { diff --git a/src/oscript/MakeAppBehavior.cs b/src/oscript/MakeAppBehavior.cs index 3c8ff4e2e..6762983c0 100644 --- a/src/oscript/MakeAppBehavior.cs +++ b/src/oscript/MakeAppBehavior.cs @@ -42,7 +42,6 @@ public override int Execute() engine.Initialize(); ScriptFileHelper.OnBeforeScriptRead(engine); var source = engine.Loader.FromFile(_codePath); - engine.SetGlobalEnvironment(new SimpleConsoleHost(), source); var compiler = engine.GetCompilerService(); var entry = compiler.CreateModule(source); diff --git a/src/oscript/SimpleConsoleHost.cs b/src/oscript/SimpleConsoleHost.cs deleted file mode 100644 index d44dc377e..000000000 --- a/src/oscript/SimpleConsoleHost.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using ScriptEngine.HostedScript; -using ScriptEngine.HostedScript.Library; - -namespace oscript -{ - internal class SimpleConsoleHost : IHostApplication - { - - public void Echo(string text, MessageStatusEnum status = MessageStatusEnum.Ordinary) - { - ConsoleHostImpl.Echo(text, status); - } - - public void ShowExceptionInfo(Exception exc) - { - ConsoleHostImpl.ShowExceptionInfo(exc); - } - - public bool InputString(out string result, int maxLen) - { - return ConsoleHostImpl.InputString(out result, maxLen); - } - - public string[] GetCommandLineArguments() - { - return null; - } - } -} diff --git a/src/oscript/oscript.csproj b/src/oscript/oscript.csproj index 24e972fad..53ef2012e 100644 --- a/src/oscript/oscript.csproj +++ b/src/oscript/oscript.csproj @@ -105,7 +105,6 @@ - From ef7e08a1f87b39089e7507608fd8154e2ad32a0a Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 26 Feb 2017 21:16:34 +0300 Subject: [PATCH 57/63] =?UTF-8?q?=D0=97=D0=B0=D0=B3=D1=80=D1=83=D0=B7?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0=BC=D1=8B?= =?UTF-8?q?=D1=85=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D0=B5=D0=B9=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B4=20=D1=81=D1=82=D0=B0=D1=80=D1=82=D0=BE?= =?UTF-8?q?=D0=BC=20=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0.=20closes?= =?UTF-8?q?=20#407?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HostedScriptEngine.cs | 16 +++++++++++++++- src/ScriptEngine.HostedScript/LibraryLoader.cs | 3 --- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index 009a3e00a..7ae8f95c5 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -10,6 +10,7 @@ This Source Code Form is subject to the terms of the using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using System.Collections.Generic; +using System.Linq; namespace ScriptEngine.HostedScript { @@ -207,7 +208,7 @@ public Process CreateProcess(IHostApplication host, ScriptModuleHandle moduleHan return InitProcess(host, ref module); } - public void SetGlobalEnvironment(IHostApplication host, ICodeSource src) + private void SetGlobalEnvironment(IHostApplication host, ICodeSource src) { _globalCtx.ApplicationHost = host; _globalCtx.CodeSource = src; @@ -217,10 +218,23 @@ public void SetGlobalEnvironment(IHostApplication host, ICodeSource src) private Process InitProcess(IHostApplication host, ref LoadedModuleHandle module) { Initialize(); + CompileDelayedModules(); + var process = new Process(host, module, _engine); return process; } + private void CompileDelayedModules() + { + var scripts = GetUserAddedScripts().Where(x => x.Type == UserAddedScriptType.Module); + foreach (var script in scripts) + { + var loaded = _engine.LoadModuleImage(script.Module); + var instance = (IValue)_engine.NewObject(loaded); + _env.SetGlobalProperty(script.Symbol, instance); + } + } + public void EnableCodeStatistics(string outputFileName) { _codeStat = new CodeStatProcessor(outputFileName); diff --git a/src/ScriptEngine.HostedScript/LibraryLoader.cs b/src/ScriptEngine.HostedScript/LibraryLoader.cs index 8e20c1a5a..153344a12 100644 --- a/src/ScriptEngine.HostedScript/LibraryLoader.cs +++ b/src/ScriptEngine.HostedScript/LibraryLoader.cs @@ -267,9 +267,6 @@ private void CompileDelayedModules() } else { - var loaded = _engine.LoadModuleImage(module); - var instance = (IValue)_engine.NewObject(loaded); - _env.SetGlobalProperty(script.identifier, instance); _env.NotifyModuleAdded(module, script.identifier); } } From 9a51c617090ff27896ef52d11afdcbcdfff7160d Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Thu, 2 Mar 2017 23:49:19 +0300 Subject: [PATCH 58/63] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D1=8F=D0=B5=D0=BC=D1=8B=D1=85=20=D0=B1=D0=B8=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D0=BE=D1=82=D0=B5=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oscript-library | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oscript-library b/oscript-library index 06fb21aea..d161c1d91 160000 --- a/oscript-library +++ b/oscript-library @@ -1 +1 @@ -Subproject commit 06fb21aea24bbfedb238c9e23306121e8b441462 +Subproject commit d161c1d9152f8009b6850bee798e746fba6d5805 From 9ad293b8aa7810f6b00cbab992ef3ed0fc2e14e3 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Fri, 3 Mar 2017 00:08:40 +0300 Subject: [PATCH 59/63] =?UTF-8?q?=D0=93=D0=B5=D0=BD=D0=B5=D1=80=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D1=82=D0=B0=D1=86=D0=B8=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D1=81?= =?UTF-8?q?=D0=B0=D0=B9=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BuildAll.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/BuildAll.csproj b/BuildAll.csproj index 623de70c6..f789892ef 100644 --- a/BuildAll.csproj +++ b/BuildAll.csproj @@ -7,6 +7,7 @@ $(OutputPathForBuild)\bin\ $(OutputPathForBuild)\lib\ $(OutputPathForBuild)\doc\ + $(MSBuildProjectDirectory)\mddoc\ $(OutputPathForBuild)\examples\ $(MSBuildProjectDirectory)\src\1Script.sln "$(InnoSetupPath)\iscc.exe" @@ -82,6 +83,7 @@ + @@ -130,6 +132,7 @@ + From 64a96a96e4510cfb8f27169b38532956a4b978e8 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Fri, 3 Mar 2017 00:54:30 +0300 Subject: [PATCH 60/63] =?UTF-8?q?=D0=9D=D0=B5=20=D0=B8=D0=BD=D0=B8=D1=86?= =?UTF-8?q?=D0=B8=D0=B0=D0=BB=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BB=D0=B8=D1=81=D1=8C=20=D0=BC=D0=BE=D0=B4=D1=83=D0=BB=D0=B8?= =?UTF-8?q?,=20=D0=BF=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D0=B2=20=D1=86=D0=B5=D0=BF=D0=BE=D1=87?= =?UTF-8?q?=D0=BA=D0=B5=20=D0=97=D0=B0=D0=BF=D1=83=D1=81=D0=BA->=D0=9F?= =?UTF-8?q?=D0=BE=D0=B4=D0=BA=D0=BB=D1=8E=D1=87=D0=B8=D1=82=D1=8C=D0=A1?= =?UTF-8?q?=D1=86=D0=B5=D0=BD=D0=B0=D1=80=D0=B8=D0=B9->=D0=98=D1=81=D0=BF?= =?UTF-8?q?=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ScriptEngine.HostedScript/HostedScriptEngine.cs | 13 ++++++++++--- src/ScriptEngine/RuntimeEnvironment.cs | 11 +++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index 7ae8f95c5..89e0fe871 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -219,6 +219,7 @@ private Process InitProcess(IHostApplication host, ref LoadedModuleHandle module { Initialize(); CompileDelayedModules(); + _env.EnvironmentChanged += LoadUserModuleAsProperty; var process = new Process(host, module, _engine); return process; @@ -229,12 +230,17 @@ private void CompileDelayedModules() var scripts = GetUserAddedScripts().Where(x => x.Type == UserAddedScriptType.Module); foreach (var script in scripts) { - var loaded = _engine.LoadModuleImage(script.Module); - var instance = (IValue)_engine.NewObject(loaded); - _env.SetGlobalProperty(script.Symbol, instance); + LoadUserModuleAsProperty(script); } } + private void LoadUserModuleAsProperty(UserAddedScript script) + { + var loaded = _engine.LoadModuleImage(script.Module); + var instance = (IValue) _engine.NewObject(loaded); + _env.SetGlobalProperty(script.Symbol, instance); + } + public void EnableCodeStatistics(string outputFileName) { _codeStat = new CodeStatProcessor(outputFileName); @@ -244,6 +250,7 @@ public void EnableCodeStatistics(string outputFileName) public void Finalize() { _codeStat?.OutputCodeStat(); + _env.EnvironmentChanged -= LoadUserModuleAsProperty; } } } diff --git a/src/ScriptEngine/RuntimeEnvironment.cs b/src/ScriptEngine/RuntimeEnvironment.cs index d44f5aab9..f8f199846 100644 --- a/src/ScriptEngine/RuntimeEnvironment.cs +++ b/src/ScriptEngine/RuntimeEnvironment.cs @@ -14,6 +14,8 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine { + public delegate void EnvironmentChangedHandler(UserAddedScript script); + public class RuntimeEnvironment { private readonly List _objects = new List(); @@ -88,14 +90,19 @@ public void NotifyClassAdded(ScriptModuleHandle module, string symbol) public void NotifyModuleAdded(ScriptModuleHandle module, string symbol) { - _externalScripts.Add(new UserAddedScript() + var script = new UserAddedScript() { Type = UserAddedScriptType.Module, Symbol = symbol, Module = module - }); + }; + + _externalScripts.Add(script); + EnvironmentChanged?.Invoke(script); } + public event EnvironmentChangedHandler EnvironmentChanged; + public IEnumerable GetUserAddedScripts() { return _externalScripts; From 2f0b44f00db8589948fa8c0b8a563b0bc7945cf2 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 5 Mar 2017 20:51:42 +0300 Subject: [PATCH 61/63] =?UTF-8?q?=D0=91=D0=B0=D0=B7=D0=BE=D0=B2=D1=8B?= =?UTF-8?q?=D0=B9=20URL=20=D0=B4=D0=BB=D1=8F=20=D1=81=D0=B8=D0=BD=D1=82?= =?UTF-8?q?=D0=B0=D0=BA=D1=81-=D0=BF=D0=BE=D0=BC=D0=BE=D1=89=D0=BD=D0=B8?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BD=D0=B0=20=D1=81=D0=B0=D0=B9=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BuildAll.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BuildAll.csproj b/BuildAll.csproj index f789892ef..30bacbbfb 100644 --- a/BuildAll.csproj +++ b/BuildAll.csproj @@ -132,7 +132,7 @@ - + From 6ef7dc83d037dabbbc1ed4ec903ac1f3d52f1fb0 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Sun, 5 Mar 2017 22:38:31 +0300 Subject: [PATCH 62/63] =?UTF-8?q?=D0=A1=D1=82=D0=B0=D0=B1=D0=B8=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=BE=20=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=85=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D1=82=D0=B5=D1=81=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/process.os | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/process.os b/tests/process.os index 805f244de..60093f701 100644 --- a/tests/process.os +++ b/tests/process.os @@ -54,11 +54,15 @@ Поток = Процесс.ПотокВывода; Стр = ""; - Пока Не Процесс.Завершен Цикл - Пока Поток.ЕстьДанные Цикл - Стр = Стр + Поток.ПрочитатьСтроку() + " - |"; - КонецЦикла; + Пока Не Процесс.Завершен ИЛИ Поток.ЕстьДанные Цикл + СтрокаПотока = Поток.ПрочитатьСтроку(); + Если СтрокаПотока = Неопределено Тогда + Приостановить(20); + Продолжить; + КонецЕсли; + + Стр = Стр + СтрокаПотока + " + |"; КонецЦикла; Стр = СокрП(Стр); From 2b022e947bcb7a0350b5e068d5bc4ccdf143465e Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Tue, 7 Mar 2017 18:28:59 +0300 Subject: [PATCH 63/63] =?UTF-8?q?=D0=A3=D0=B4=D0=B0=D0=BB=D0=BE=D1=81?= =?UTF-8?q?=D1=8C=20=D0=B7=D0=B0=D0=BB=D0=B5=D1=87=D0=B8=D1=82=D1=8C=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D1=83=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B4=D1=83=D0=BB=D0=B5=D0=B9,=20=D0=B8=D1=81=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=B7=D1=83=D1=8E=D1=89=D0=B8=D1=85=20=D0=B5=D1=89?= =?UTF-8?q?=D0=B5=20=D0=BD=D0=B5=D0=B7=D0=B0=D0=B3=D1=80=D1=83=D0=B6=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=BB=D0=B0=D1=81=D1=81=D1=8B?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HostedScriptEngine.cs | 23 ++----------------- .../LibraryLoader.cs | 2 ++ src/ScriptEngine/RuntimeEnvironment.cs | 12 ++++++---- src/ScriptEngine/ScriptingEngine.cs | 14 +++++++++++ 4 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index 89e0fe871..8847432c5 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -218,29 +218,11 @@ private void SetGlobalEnvironment(IHostApplication host, ICodeSource src) private Process InitProcess(IHostApplication host, ref LoadedModuleHandle module) { Initialize(); - CompileDelayedModules(); - _env.EnvironmentChanged += LoadUserModuleAsProperty; - + var process = new Process(host, module, _engine); return process; } - - private void CompileDelayedModules() - { - var scripts = GetUserAddedScripts().Where(x => x.Type == UserAddedScriptType.Module); - foreach (var script in scripts) - { - LoadUserModuleAsProperty(script); - } - } - - private void LoadUserModuleAsProperty(UserAddedScript script) - { - var loaded = _engine.LoadModuleImage(script.Module); - var instance = (IValue) _engine.NewObject(loaded); - _env.SetGlobalProperty(script.Symbol, instance); - } - + public void EnableCodeStatistics(string outputFileName) { _codeStat = new CodeStatProcessor(outputFileName); @@ -250,7 +232,6 @@ public void EnableCodeStatistics(string outputFileName) public void Finalize() { _codeStat?.OutputCodeStat(); - _env.EnvironmentChanged -= LoadUserModuleAsProperty; } } } diff --git a/src/ScriptEngine.HostedScript/LibraryLoader.cs b/src/ScriptEngine.HostedScript/LibraryLoader.cs index 153344a12..c26cd46e5 100644 --- a/src/ScriptEngine.HostedScript/LibraryLoader.cs +++ b/src/ScriptEngine.HostedScript/LibraryLoader.cs @@ -271,6 +271,8 @@ private void CompileDelayedModules() } } + _engine.CompileEnvironmentModules(_env); + } } } diff --git a/src/ScriptEngine/RuntimeEnvironment.cs b/src/ScriptEngine/RuntimeEnvironment.cs index f8f199846..c1fef102b 100644 --- a/src/ScriptEngine/RuntimeEnvironment.cs +++ b/src/ScriptEngine/RuntimeEnvironment.cs @@ -14,8 +14,6 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine { - public delegate void EnvironmentChangedHandler(UserAddedScript script); - public class RuntimeEnvironment { private readonly List _objects = new List(); @@ -62,6 +60,12 @@ public void SetGlobalProperty(string propertyName, IValue value) _injectedProperties.SetPropValue(propId, value); } + public IValue GetGlobalProperty(string propertyName) + { + int propId = _injectedProperties.FindProperty(propertyName); + return _injectedProperties.GetPropValue(propId); + } + internal CompilerContext SymbolsContext { get @@ -98,10 +102,8 @@ public void NotifyModuleAdded(ScriptModuleHandle module, string symbol) }; _externalScripts.Add(script); - EnvironmentChanged?.Invoke(script); + SetGlobalProperty(script.Symbol, null); } - - public event EnvironmentChangedHandler EnvironmentChanged; public IEnumerable GetUserAddedScripts() { diff --git a/src/ScriptEngine/ScriptingEngine.cs b/src/ScriptEngine/ScriptingEngine.cs index 7f810395b..300687999 100644 --- a/src/ScriptEngine/ScriptingEngine.cs +++ b/src/ScriptEngine/ScriptingEngine.cs @@ -5,6 +5,8 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; +using System.Linq; + using ScriptEngine.Compiler; using ScriptEngine.Environment; using ScriptEngine.Machine; @@ -160,5 +162,17 @@ public void Dispose() #endregion + public void CompileEnvironmentModules(RuntimeEnvironment env) + { + var scripts = env.GetUserAddedScripts().Where(x => x.Type == UserAddedScriptType.Module && env.GetGlobalProperty(x.Symbol) == null); + + foreach (var script in scripts) + { + var loaded = LoadModuleImage(script.Module); + var instance = (IValue)NewObject(loaded); + env.SetGlobalProperty(script.Symbol, instance); + } + } + } }