From 54d50e25fc6446f77256e0e47b2dca3765eea3fa Mon Sep 17 00:00:00 2001 From: Arc <87562566+Arc-huangjingtong@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:44:24 +0800 Subject: [PATCH] Update --- .../UniInkSpeed/NUnit_UniInkSpeed.cs | 81 +++--- Arc.UniInk/Arc.UniInk.sln.DotSettings.user | 20 +- Arc.UniInk/Arc.UniInk/UniInk_Extensions.cs | 241 ++++++++++-------- Arc.UniInk/Arc.UniInk/UniInk_Speed.cs | 12 +- 4 files changed, 197 insertions(+), 157 deletions(-) diff --git a/Arc.UniInk/Arc.UniInk.Benchmark/UniInkSpeed/NUnit_UniInkSpeed.cs b/Arc.UniInk/Arc.UniInk.Benchmark/UniInkSpeed/NUnit_UniInkSpeed.cs index 5719a53..723f09f 100644 --- a/Arc.UniInk/Arc.UniInk.Benchmark/UniInkSpeed/NUnit_UniInkSpeed.cs +++ b/Arc.UniInk/Arc.UniInk.Benchmark/UniInkSpeed/NUnit_UniInkSpeed.cs @@ -16,6 +16,7 @@ using Arc.UniInk; using System; using System.Collections.Generic; + using JetBrains.Util; using NUnit.Framework; @@ -377,31 +378,49 @@ public static void Test_Temp() /////////////////////////////////////////////// Extension Test //////////////////////////////////////////////// - // [Repeat(10)] - // [TestCase(" if( 1 > 2 ) " - // + " { " - // + " 123 " - // + " } " - // + " else " - // + " { " - // + " 456 " - // + " } ")] - // ///////////////////////////////////// - // [TestCase(" if( 1 > 2 ) " - // + " { " - // + " 123 " - // + " } " - // + " else if (3>6) " - // + " { " - // + " 456 " - // + " } " - // + " else " - // + " { " - // + " 666 " - // + " } ")] + //[Repeat(1)] + /////////////////////////////////////// + [TestCase(" if ( 1 > 2 ) " + + " { " + + " 123 " + + " } " + + " else " + + " { " + + " return 456 " + + " } ")] + /////////////////////////////////////// + [TestCase(" if ( 1 > 2 ) " + + " { " + + " 123 " + + " } " + + " else if ( 3 > 6 ) " + + " { " + + " 456 " + + " } " + + " else " + + " { " + + " return 666 " + + " } ")] + /////////////////////////////////////// + [TestCase(" if ( 1 > 2 ) " + + " { " + + " 123 " + + " } " + + " else if ( 3 > 6 ) " + + " { " + + " 456 " + + " } " + + " else if ( 3 < 6 ) " + + " { " + + " return 456 " + + " } " + + " else " + + " { " + + " return 666 " + + " } ")] public static void Test_Expression_IfStatements(string input) { - var test = Ink.Evaluate(input); + var test = Ink.Evaluate_IfStatement(input); if (test is InkValue value) { Console.WriteLine(value.Value_int); // each time , the result will be different @@ -410,22 +429,6 @@ public static void Test_Expression_IfStatements(string input) } } - [TestCase("((((((()()()()()))))))")] - [TestCase("()")] - [TestCase("()()")] - [TestCase("(())(())")] - public static void Temp_Function_GetMatchOperator(string input) - { - var keys = Ink.CompileLexerAndFill(input, 0, input.Length - 1); - - Console.WriteLine(keys.Count); - - var res = UniInk_Speed.GetMatchOperator(keys, InkOperator.ParenthisLeft, InkOperator.ParenthisRight, 0, keys.Count - 1); - - Console.WriteLine(res.StartIndex); - Console.WriteLine(res.EndIndex); - } - /////////////////////////////////////////////// Helper Object //////////////////////////////////////////////// diff --git a/Arc.UniInk/Arc.UniInk.sln.DotSettings.user b/Arc.UniInk/Arc.UniInk.sln.DotSettings.user index 181f3ca..0e1697c 100644 --- a/Arc.UniInk/Arc.UniInk.sln.DotSettings.user +++ b/Arc.UniInk/Arc.UniInk.sln.DotSettings.user @@ -15,14 +15,26 @@ <Assembly Path="F:\UniInk-CSharpInterpreter4AOT\Arc.UniInk\packages\BenchmarkDotNet.Annotations.0.13.12\lib\netstandard2.0\BenchmarkDotNet.Annotations.dll" /> </AssemblyExplorer> True - <SessionState ContinuousTestingMode="0" IsActive="True" Name="Test_Expression_IfStatements" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <SessionState ContinuousTestingMode="0" IsActive="True" Name="Test_Expression_IfStatements" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> <TestAncestor> - <TestId>NUnit3x::1BA70864-1706-44D0-9D58-669FD5703A14::.NETFramework,Version=v4.8::Arc.UniInk.NUnitTest.NUnit_UniInkSpeed.Test_Arithmetic_Float</TestId> - <TestId>NUnit3x::1BA70864-1706-44D0-9D58-669FD5703A14::.NETFramework,Version=v4.8::Arc.UniInk.NUnitTest.NUnit_UniInkSpeed.Test_Arithmetic_Int("9*((1+(2+3)*(4+5))+6+7)")</TestId> - <TestId>NUnit3x::1BA70864-1706-44D0-9D58-669FD5703A14::.NETFramework,Version=v4.8::Arc.UniInk.NUnitTest.NUnit_UniInkSpeed.Test_Arithmetic_Int</TestId> + <TestId>NUnit3x::1BA70864-1706-44D0-9D58-669FD5703A14::.NETFramework,Version=v4.8::Arc.UniInk.NUnitTest.NUnit_UniInkSpeed.Test_Expression_IfStatements</TestId> </TestAncestor> </SessionState> + <SessionState ContinuousTestingMode="0" Name="Test_Expression_IfStatements #3" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <TestAncestor> + <TestId>NUnit3x::1BA70864-1706-44D0-9D58-669FD5703A14::.NETFramework,Version=v4.8::Arc.UniInk.NUnitTest.NUnit_UniInkSpeed.Test_Expression_IfStatements</TestId> + </TestAncestor> +</SessionState> + <SessionState ContinuousTestingMode="0" Name="Test_Expression_IfStatements #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <TestAncestor> + <TestId>NUnit3x::1BA70864-1706-44D0-9D58-669FD5703A14::.NETFramework,Version=v4.8::Arc.UniInk.NUnitTest.NUnit_UniInkSpeed.Test_Expression_IfStatements</TestId> + </TestAncestor> +</SessionState> + + + + diff --git a/Arc.UniInk/Arc.UniInk/UniInk_Extensions.cs b/Arc.UniInk/Arc.UniInk/UniInk_Extensions.cs index c3711dd..7d5177e 100644 --- a/Arc.UniInk/Arc.UniInk/UniInk_Extensions.cs +++ b/Arc.UniInk/Arc.UniInk/UniInk_Extensions.cs @@ -1,7 +1,6 @@ namespace Arc.UniInk { - using System; using System.Text.RegularExpressions; @@ -13,47 +12,6 @@ /*******************************************************************************************************************/ - /// Provide commonly tools in - /// not assurance zero GC - public static class UniInk_Extensions - { - #region Remove comments - - - //Base on : https://stackoverflow.com/questions/3524317/regex-to-strip-line-comments-from-c-sharp/3524689#3524689 - private static readonly Regex removeCommentsRegex = new($"{blockComments}|{lineComments}|{stringsIgnore}|{verbatimStringsIgnore}", RegexOptions.Singleline | RegexOptions.Compiled); - private static readonly Regex newLineCharsRegex = new(@"\r\n|\r|\n", RegexOptions.Compiled); - - private const string verbatimStringsIgnore = @"@(""[^""]*"")+"; //language=regex - private const string stringsIgnore = @"""((\\[^\n]|[^""\n])*)"""; //language=regex - private const string blockComments = @"/\*(.*?)\*/"; //language=regex - private const string lineComments = @"//[^\r\n]*"; //language=regex - - - /// Remove all line and block comments from the specified C# script - /// C# script without comments - /// C# script with comments - public static string RemoveComments(string scriptWithComments) - { - return removeCommentsRegex.Replace(scriptWithComments, Evaluator); - - string Evaluator(Match match) - { - if (match.Value.StartsWith("/")) - { - var newLineCharsMatch = newLineCharsRegex.Match(match.Value); - - return match.Value.StartsWith("/*") && newLineCharsMatch.Success ? newLineCharsMatch.Value : " "; - } - - return match.Value; - } - } - - - #endregion - } - #region Support for UniInk_Speed : If Statement @@ -64,41 +22,56 @@ public partial class UniInk_Speed /// Not support Nested if statement protected static object ProcessList_ScriptsWithIfStatement(InkSyntaxList keys) { - var start = 0; - var end = keys.Count - 1; - object res; + var index_start = 0; + var index_end = keys.Count - 1; + object res = null; while (true) { //找到第一个[if] - var (success_if, index_if) = FindOperator(keys, InkOperator.KeyIf, start, end); + var (success_if, index_if) = FindOperator(keys, InkOperator.KeyIf, index_start, index_end); //找到第一个[ ;] - var (success_semi, index_semi) = FindOperator(keys, InkOperator.Semicolon, start, end); + var (success_semi, index_semi) = FindOperator(keys, InkOperator.Semicolon, index_start, index_end); if (success_semi && index_semi < index_if) { - ProcessList(keys, start, index_semi - 1); + ProcessList(keys, index_start, index_semi - 1); keys.SetDirty(index_semi); - start = index_semi + 1; + index_start = index_semi + 1; continue; } if (success_if && index_if < index_semi) { - ProcessList_IfStatement(keys, index_if); + var current = ProcessList_IfStatement(keys, index_if); + + keys.SetDirty(null, index_start, current); + index_start = current + 1; continue; } - - res = ProcessList(keys, start, index_semi); //index is the last index + if (index_start < index_end) + { + res = ProcessList(keys, index_start, index_semi); //index is the last index + } break; } + for (var i = 0 ; i < keys.Count ; i++) + { + if (keys.CastOther[i] is InkValue { returner: true } value) + { + res = value.Clone(); + } + } + return res; } + /// Process the if statement + /// Return the processed lasted operator [}] protected static int ProcessList_IfStatement(InkSyntaxList keys, int start) { // Begin : keyword [if] (condition) { operation } Open : [if] flag @@ -106,6 +79,8 @@ protected static int ProcessList_IfStatement(InkSyntaxList keys, int start) // End : keyword [else] { operation } need : [if] flag and close [if] flag // 这个函数会被检测函数调用,那么一开始一定有一个 If 关键字 + + // 定位 If(condition) 条件的开始和结束 var (conditionStart, conditionEnd) = GetMatchOperator(keys, InkOperator.ParenthisLeft, InkOperator.ParenthisRight, start, keys.Count - 1); @@ -116,7 +91,7 @@ protected static int ProcessList_IfStatement(InkSyntaxList keys, int start) } - // 定位操作的开始和结束 + // 定位If(condition){ operation } 操作的开始和结束 var (operationStart, operationEnd) = GetMatchOperator(keys, InkOperator.BraceLeft, InkOperator.BraceRight, conditionEnd + 1, keys.Count - 1); @@ -129,6 +104,7 @@ protected static int ProcessList_IfStatement(InkSyntaxList keys, int start) var flag_result = false; var ifCondition = false; var currentEnd = operationEnd; + var index_end = keys.Count - 1; // 计算条件 @@ -141,18 +117,14 @@ protected static int ProcessList_IfStatement(InkSyntaxList keys, int start) ifCondition = true; ProcessList(keys, operationStart + 1, operationEnd - 1); } - else - { - ifCondition = false; - } } while (true) { // Check the position relationship between the next else and if, and then enumerate all cases based on their relationship (very elegant) - var (success_else, index_else) = FindOperator(keys, InkOperator.KeyElse, operationEnd + 1, keys.Count - 1); - var (success_if, index_if) = FindOperator(keys, InkOperator.KeyIf, operationEnd + 1, keys.Count - 1); + var (success_else, index_else) = FindOperator(keys, InkOperator.KeyElse, currentEnd + 1, index_end); + var (success_if, index_if) = FindOperator(keys, InkOperator.KeyIf, currentEnd + 1, index_end); // 1. 如果没有找到 else 和 if , 直接退出If 结算 , 说明后面再也没有 If 语句了 , 交给下一个循环即可 // 2. 如果找到了 if , 没找到 else , 说明这是一个 if 语句 , 交给下一个循环即可 @@ -162,20 +134,26 @@ protected static int ProcessList_IfStatement(InkSyntaxList keys, int start) switch (success_else, success_if, index_if - index_else) { - case (false, false, _) : return operationEnd; - case (false, true, _) : return operationEnd; + case (false, false, _) : return currentEnd; + case (false, true, _) : return currentEnd; case (true, false, _) : case (true, true, > 1) : { + var temp_start = index_else + 1; + + if (success_if) temp_start++; + var (opElseStart, opElseEnd) - = GetMatchOperator(keys, InkOperator.BraceLeft, InkOperator.BraceRight, index_else + 1, keys.Count - 1); + = GetMatchOperator(keys, InkOperator.BraceLeft, InkOperator.BraceRight, temp_start, keys.Count - 1); if (!ifCondition) { ProcessList(keys, opElseStart + 1, opElseEnd - 1); } - return opElseEnd; + currentEnd = opElseEnd; + + return currentEnd; } case (true, true, 1) : // else if { @@ -194,75 +172,120 @@ protected static int ProcessList_IfStatement(InkSyntaxList keys, int start) //FuncA(); //FuncB(); - // 匹配 else if 后的条件 + // 匹配 else if (condition) 后的条件 var (cdsStart, cdsEnd) - = GetMatchOperator(keys, InkOperator.ParenthisLeft, InkOperator.ParenthisRight, index_if + 1, keys.Count - 1); + = GetMatchOperator(keys, InkOperator.ParenthisLeft, InkOperator.ParenthisRight, index_if + 1, index_end); // 计算 else if 条件后的操作 var (opElseStart, opElseEnd) - = GetMatchOperator(keys, InkOperator.BraceLeft, InkOperator.BraceRight, cdsEnd + 1, keys.Count - 1); + = GetMatchOperator(keys, InkOperator.BraceLeft, InkOperator.BraceRight, cdsEnd + 1, index_end); - if (!ifCondition) //如果还没有找到正确的条件 - { - // 计算 else if 后的条件 - var condition_elseif = ProcessList(keys, cdsStart + 1, cdsEnd - 1); - if (condition_elseif is InkValue conditionValue_elseif) - { - ifCondition = conditionValue_elseif; - } + // 计算 else if 后的条件 + var condition_elseif = ProcessList(keys, cdsStart + 1, cdsEnd - 1); - if (!ifCondition) + if (condition_elseif is InkValue conditionValue_elseif) + { + if (conditionValue_elseif && ifCondition == false) { ProcessList(keys, opElseStart + 1, opElseEnd - 1); } - } + ifCondition = conditionValue_elseif || ifCondition; + } + currentEnd = opElseEnd; break; } } } } + /// Judge the input String is a Script or not (depend on the operator:[;] [{]) + protected static bool InputIsScript_IfStatement(InkSyntaxList keys) + { + foreach (var obj in keys.ObjectList) + { + //match [;] or [{] + if (obj is InkOperator op && (Equals(op, InkOperator.Semicolon) || Equals(op, InkOperator.BraceLeft))) + { + return true; + } + } + + + return false; + } + + public static object ExecuteProcess_IfStatement(InkSyntaxList keys) + { + var res = InputIsScript_IfStatement(keys) ? ProcessList_ScriptsWithIfStatement(keys) : ProcessList(keys, 0, keys.Count - 1); + + return res; + } + /// Evaluate the expression with the if statement + public object Evaluate_IfStatement(string expression, int startIndex, int endIndex) + { + var keys = CompileLexerAndFill(expression, startIndex, endIndex); + + var result = ExecuteProcess_IfStatement(keys); - // the sign of an if statement: - // Begin : keyword [if] (condition) { operation } - // Then : keyword [else if] (condition) { operation } need : [if] - // End : keyword [else] { operation } need : [if] and close [if] - - - - // if (Has State Keywords) - // { - // - // - // - // While (true) - // { - // var (hasState , ConditionPartStart , ConditionPartEnd , OperationStart , OperationEnd) = GetStatementPart(); - // var result = ProcessList(keys, OperationStart, OperationEnd); - // if (hasState == false) - // { - // break; - // } - // else if (result == true) - // { - // - // ProcessList(keys, OperationStart, OperationEnd); (recursion) - // var end = GetStatementEnd(); // get the end of the statement , and jump to ; - // SetDirty(..end); - // } - // else - // { - // continue; - // } - // } - // } + RecoverResources(keys); + + return result; + } + + public object Evaluate_IfStatement(string expression) + { + return Evaluate_IfStatement(expression, 0, expression.Length - 1); + } } #endregion + + + /// Provide commonly tools in + /// not assurance zero GC + public static class UniInk_Extensions + { + #region Remove comments + + + //Base on : https://stackoverflow.com/questions/3524317/regex-to-strip-line-comments-from-c-sharp/3524689#3524689 + private static readonly Regex removeCommentsRegex = new($"{blockComments}|{lineComments}|{stringsIgnore}|{verbatimStringsIgnore}", RegexOptions.Singleline | RegexOptions.Compiled); + private static readonly Regex newLineCharsRegex = new(@"\r\n|\r|\n", RegexOptions.Compiled); + + private const string verbatimStringsIgnore = @"@(""[^""]*"")+"; //language=regex + private const string stringsIgnore = @"""((\\[^\n]|[^""\n])*)"""; //language=regex + private const string blockComments = @"/\*(.*?)\*/"; //language=regex + private const string lineComments = @"//[^\r\n]*"; //language=regex + + + /// Remove all line and block comments from the specified C# script + /// C# script without comments + /// C# script with comments + public static string RemoveComments(string scriptWithComments) + { + return removeCommentsRegex.Replace(scriptWithComments, Evaluator); + + string Evaluator(Match match) + { + if (match.Value.StartsWith("/")) + { + var newLineCharsMatch = newLineCharsRegex.Match(match.Value); + + return match.Value.StartsWith("/*") && newLineCharsMatch.Success ? newLineCharsMatch.Value : " "; + } + + return match.Value; + } + } + + + #endregion + } + } \ No newline at end of file diff --git a/Arc.UniInk/Arc.UniInk/UniInk_Speed.cs b/Arc.UniInk/Arc.UniInk/UniInk_Speed.cs index e5150d2..1629eb3 100644 --- a/Arc.UniInk/Arc.UniInk/UniInk_Speed.cs +++ b/Arc.UniInk/Arc.UniInk/UniInk_Speed.cs @@ -978,7 +978,7 @@ protected static (bool result, int startIndex, int endIndex) FindSection(InkSynt } /// Find the outermost operator range in the specified left and right - public static (int StartIndex, int EndIndex) GetMatchOperator(InkSyntaxList keys, InkOperator opLeft, InkOperator opRight, int start, int end) + protected static (int StartIndex, int EndIndex) GetMatchOperator(InkSyntaxList keys, InkOperator opLeft, InkOperator opRight, int start, int end) { int startIndex = -1, balance = -1; @@ -1107,8 +1107,8 @@ protected static bool InputIsScript(InkSyntaxList keys) { foreach (var obj in keys.ObjectList) { - //match [;] or [{] - if (obj is InkOperator @operator && (Equals(@operator, InkOperator.Semicolon) || Equals(@operator, InkOperator.BraceLeft))) + //match [;] + if (obj is InkOperator @operator && Equals(@operator, InkOperator.Semicolon)) { return true; } @@ -1442,6 +1442,7 @@ public static object InkOperator_Return(object left, object right) { case InkValue rightValue : { + rightValue.Calculate(); var result = rightValue.Clone(); result.returner = true; return result; @@ -1579,6 +1580,9 @@ public static void Release(InkValue value) value.Value_Meta.Clear(); value.isCalculate = false; + value.setter = false; + value.getter = false; + value.returner = false; pool.Enqueue(value); } @@ -2072,8 +2076,6 @@ public static void Recover(InkSyntaxList value) public readonly List CastOther = new(UniInk_Speed.CAPACITY_LIST); public readonly List IndexDirty = new(UniInk_Speed.CAPACITY_LIST); - public object ReturnObject = null; - public void Add(object value)