diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index f88dbdd4f..76076c356 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -14,8 +14,8 @@ internal static class RevisionClass { public const string Major = "3"; public const string Minor = "10"; - public const string Build = "2"; - public const string Revision = "3597"; + public const string Build = "3"; + public const string Revision = "3602"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 8cc06586a..561c69a5d 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ +%COREVERSION%=3 +%REVISION%=3602 %MINOR%=10 -%REVISION%=3597 -%COREVERSION%=2 %MAJOR%=3 diff --git a/InstallerSamples/WhatsNew/3_10_3/faststring1.pas b/InstallerSamples/WhatsNew/3_10_3/faststring1.pas new file mode 100644 index 000000000..868bcb611 --- /dev/null +++ b/InstallerSamples/WhatsNew/3_10_3/faststring1.pas @@ -0,0 +1,14 @@ +// 6.0 sec PascalABC.NET vs 11.4 sec Python +begin + var mx := 0; + for var n := 4 to 9999 do + begin + var s: faststring := '4' + '1' * n; + + while ('411' in s) or ('1111' in s) do + s.Replace('411', '14', 1).Replace('1111', '1', 1); + + mx := max(mx, s.ToString.Sum(d -> d.todigit)); + end; + print(mx, Milliseconds / 1000); +end. \ No newline at end of file diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index bc7ffd4b8..7e294f09a 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.10.2.3597 +3.10.3.3602 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 82ee1e15e..218703934 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.10.2.3597' +!define VERSION '3.10.3.3602' diff --git a/SyntaxTree/tree/NodesBuilder.cs b/SyntaxTree/tree/NodesBuilder.cs index b0ba48b55..da3002e5d 100644 --- a/SyntaxTree/tree/NodesBuilder.cs +++ b/SyntaxTree/tree/NodesBuilder.cs @@ -5,6 +5,8 @@ using System.Text; namespace PascalABCCompiler.SyntaxTree { + // По идее из разных мест сюда всё собрано в три разных хаотичных класса + #region Генерация новых узлов синтаксического дерева /// /// Класс для генерации новых узлов синтаксического дерева @@ -295,11 +297,11 @@ namespace PascalABCCompiler.SyntaxTree private static procedure_definition InternalCreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, SourceContext sc) { return SyntaxTreeNodesConstructor.CreateProcedureDefinitionNode(new method_name(methName), - formalPars, - false, - classKeyword, - procBody, - sc); + formalPars, + false, + classKeyword, + procBody, + sc); } public static procedure_definition CreateProcedureDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, SourceContext sc) @@ -315,12 +317,12 @@ namespace PascalABCCompiler.SyntaxTree private static procedure_definition InternalCreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType, SourceContext sc) { return SyntaxTreeNodesConstructor.CreateFunctionDefinitionNode(new method_name(methName), - formalPars, - false, - classKeyword, - procBody, - returnType, - sc); + formalPars, + false, + classKeyword, + procBody, + returnType, + sc); } public static procedure_definition CreateFunctionDefinitionNode(string methName, formal_parameters formalPars, bool classKeyword, statement procBody, type_definition returnType, SourceContext sc) @@ -355,10 +357,14 @@ namespace PascalABCCompiler.SyntaxTree public static SourceContext BuildGenSC = new SourceContext(0, 777777, 0, 0, 0, 0); private static int GenIdNum = 0; - public static ident GenIdentName() + public static string UniqueString() { GenIdNum++; - return new ident("$GenId" + GenIdNum.ToString()); + return GenIdNum.ToString(); + } + public static ident GenIdentName() + { + return new ident("$GenId" + UniqueString()); } public static type_definition BuildSimpleType(string name) @@ -420,6 +426,23 @@ namespace PascalABCCompiler.SyntaxTree return sl; } + // SSM 25.01.25 + public static procedure_definition BuildSimpleFunction(string name, List paramNames, List paramTypes, type_definition returnType, statement procBody, SourceContext sc = null) + { + var fp = SyntaxTreeBuilder.BuildFormalParameters(paramNames, paramTypes); + var fdn = SyntaxTreeNodesConstructor.CreateFunctionDefinitionNode(new method_name(name), fp, false, false, procBody, returnType, sc); + return fdn; + } + public static procedure_definition BuildSimpleFunctionOneParameter(string name, string paramName, type_definition paramType, type_definition returnType, statement procBody, SourceContext sc = null) + { + var lstNames = new List(); + lstNames.Add(new ident(paramName)); + var lstTypes = new List(); + lstTypes.Add(paramType); + var fp = SyntaxTreeBuilder.BuildFormalParameters(lstNames, lstTypes); + var fdn = SyntaxTreeNodesConstructor.CreateFunctionDefinitionNode(new method_name(name), fp, false, false, procBody, returnType, sc); + return fdn; + } public static procedure_definition BuildSimpleConstructor(List fields, List formal_names, List types) { var fp = SyntaxTreeBuilder.BuildFormalParameters(formal_names, types); diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index a544854a4..052651fe7 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -105,7 +105,7 @@ type /// Представляет произвольно большое целое число BigInteger = System.Numerics.BigInteger; - + /// Представляет дату и время DateTime = System.DateTime; @@ -181,6 +181,9 @@ type /// Представляет изменяемую строку символов StringBuilder = System.Text.StringBuilder; + /// Представляет строку с эффективным изменением + faststring = StringBuilder; + /// Тип кодировки символов Encoding = System.Text.Encoding; @@ -483,7 +486,7 @@ type end;} type - NewSetEmpty = class; + EmptyCollection = class; /// Тип встроенного множества NewSet = record(IEnumerable) @@ -558,66 +561,77 @@ type begin Result._hs := new HashSet(a); end; - - static function operator implicit(ns: NewSetEmpty): NewSet; begin end; static function operator:=(var s: NewSet; st: NewSet): NewSet; // Эту функцию обязательно здесь определять begin s._hs := new HashSet(st.hs); end; + static function operator implicit(ns: EmptyCollection): NewSet; begin end; end; - NewSetEmpty = class + EmptyCollection = class public - static function operator=(s1: NewSet; s2: NewSetEmpty): boolean := s1.Count = 0; - static function operator=(s2: NewSetEmpty; s1: NewSet): boolean := s1.Count = 0; - static function operator<>(s1: NewSet; s2: NewSetEmpty): boolean := not (s1 = s2); - static function operator<>(s2: NewSetEmpty; s1: NewSet): boolean := not (s1 = s2); - static function operator>(s1: NewSet; s2: NewSetEmpty): boolean := s1.Count > 0; - static function operator>(s2: NewSetEmpty; s1: NewSet): boolean := False; - static function operator<(s1: NewSet; s2: NewSetEmpty): boolean := False; - static function operator<(s2: NewSetEmpty; s1: NewSet): boolean := s1.Count > 0; - static function operator>=(s1: NewSet; s2: NewSetEmpty): boolean := s1.Count >= 0; - static function operator>=(s2: NewSetEmpty; s1: NewSet): boolean := False; - static function operator<=(s1: NewSet; s2: NewSetEmpty): boolean := False; - static function operator<=(s2: NewSetEmpty; s1: NewSet): boolean := s1.Count >= 0; + static function operator=(s1: NewSet; s2: EmptyCollection): boolean := s1.Count = 0; + static function operator=(s2: EmptyCollection; s1: NewSet): boolean := s1.Count = 0; + static function operator<>(s1: NewSet; s2: EmptyCollection): boolean := not (s1 = s2); + static function operator<>(s2: EmptyCollection; s1: NewSet): boolean := not (s1 = s2); + static function operator>(s1: NewSet; s2: EmptyCollection): boolean := s1.Count > 0; + static function operator>(s2: EmptyCollection; s1: NewSet): boolean := False; + static function operator<(s1: NewSet; s2: EmptyCollection): boolean := False; + static function operator<(s2: EmptyCollection; s1: NewSet): boolean := s1.Count > 0; + static function operator>=(s1: NewSet; s2: EmptyCollection): boolean := s1.Count >= 0; + static function operator>=(s2: EmptyCollection; s1: NewSet): boolean := False; + static function operator<=(s1: NewSet; s2: EmptyCollection): boolean := False; + static function operator<=(s2: EmptyCollection; s1: NewSet): boolean := s1.Count >= 0; // ToDo: определить то же для массивов на будущее - static function operator+(first, second: NewSetEmpty): NewSetEmpty := new NewSetEmpty; - static function operator-(first, second: NewSetEmpty): NewSetEmpty := new NewSetEmpty; - static function operator*(first, second: NewSetEmpty): NewSetEmpty := new NewSetEmpty; - static function operator+(first: NewSetEmpty; second: array of T): NewSet; + static function operator+(first, second: EmptyCollection): EmptyCollection := new EmptyCollection; + static function operator-(first, second: EmptyCollection): EmptyCollection := new EmptyCollection; + static function operator*(first, second: EmptyCollection): EmptyCollection := new EmptyCollection; + static function operator+(first: EmptyCollection; second: array of T): NewSet; begin Result.hs.UnionWith(second); end; - static function operator+(first: array of T; second: NewSetEmpty): NewSet; + static function operator+(first: array of T; second: EmptyCollection): NewSet; begin Result.hs.UnionWith(first); end; - static function operator+(first: NewSet; second: NewSetEmpty): NewSet := first; - static function operator+(first: NewSetEmpty; second: NewSet): NewSet := second; - static function operator*(first: NewSet; second: NewSetEmpty): NewSet; begin end; - static function operator*(first: NewSetEmpty; second: NewSet): NewSet; begin end; - static function operator-(first: NewSet; second: NewSetEmpty): NewSet := first; - static function operator-(first: NewSetEmpty; second: NewSet): NewSet; begin end; + static function operator+(first: NewSet; second: EmptyCollection): NewSet := first; + static function operator+(first: EmptyCollection; second: NewSet): NewSet := second; + static function operator*(first: NewSet; second: EmptyCollection): NewSet; begin end; + static function operator*(first: EmptyCollection; second: NewSet): NewSet; begin end; + static function operator-(first: NewSet; second: EmptyCollection): NewSet := first; + static function operator-(first: EmptyCollection; second: NewSet): NewSet; begin end; - static function operator*(first: NewSetEmpty; second: array of T): NewSet; begin end; - static function operator*(first: array of T; second: NewSetEmpty): NewSet; begin end; - static function operator-(first: NewSetEmpty; second: array of T): NewSet; begin end; - static function operator-(first: array of T; second: NewSetEmpty): NewSet; + static function operator*(first: EmptyCollection; second: array of T): NewSet; begin end; + static function operator*(first: array of T; second: EmptyCollection): NewSet; begin end; + static function operator-(first: EmptyCollection; second: array of T): NewSet; begin end; + static function operator-(first: array of T; second: EmptyCollection): NewSet; begin Result.hs.UnionWith(first); end; function ToString: string; override := '{}'; function ToSet(): NewSet; begin end; - static function operator implicit(Self: NewSetEmpty): array of T; + static function operator implicit(Self: EmptyCollection): array of T; begin - Result := new T[0]; + Result := new T[0]//System.Array.Empty&; end; - static function operator implicit(Self: NewSetEmpty): HashSet; + static function operator implicit(Self: EmptyCollection): HashSet; begin Result := new HashSet; end; + static function operator implicit(Self: EmptyCollection): SortedSet; + begin + Result := new SortedSet; + end; + static function operator implicit(Self: EmptyCollection): List; + begin + Result := new List; + end; + static function operator implicit(Self: EmptyCollection): Dictionary; + begin + Result := new Dictionary; + end; end; type @@ -667,7 +681,7 @@ type end; /// Значение пустого множества -function EmptySet: NewSetEmpty; +function EmptySet: EmptyCollection; /// Генератор множества function __NewSetCreatorInternal(params a: array of T): NewSet; @@ -14689,6 +14703,81 @@ begin &to.IndexValue := Self.Count - &to.IndexValue + 1; Result := SystemSliceStringImplQuestion(Self, situation, from.IndexValue, &to.IndexValue, step, 0); end; + +//-------------------------------------------- +//>> Методы расширения типа faststring (StringBuilder) # Extension methods for faststring (StringBuilder) +//-------------------------------------------- +/// Возвращает индекс вхождения подстроки в быструю строку +function IndexOf(Self: faststring; subs: string; from: integer := 0): integer; extensionmethod; +begin + var lens := Self.Length; + var lens1 := subs.Length; + + if (from < 0) or (lens1 > lens - from) then + begin + Result := -1; + exit; + end; + + if lens1 = 0 then + begin + Result := from; + exit; + end; + + for var i := from to lens - lens1 do + begin + var found := True; + for var j := 0 to lens1 - 1 do + begin + if Self[i + j] <> subs[j + 1] then + begin + found := False; + break; + end; + end; + + if found then + begin + Result := i; + exit; + end; + end; + + Result := -1; +end; + +/// Преобразует быструю строку в последовательность символов +function ToSequence(Self: faststring): sequence of char; extensionmethod; +begin + for var i:=0 to Self.Length - 1 do + yield Self[i]; +end; + +function operator in(subs: string; s: faststring): boolean; extensionmethod; +begin + Result := s.IndexOf(subs) <> -1; +end; + +/// Замещает n вхождений указанной строки на другую строку (все при n = 0) +function Replace(Self: faststring; OldValue, NewValue: string; n: integer): faststring; extensionmethod; +begin + if n = 0 then + Self.Replace(OldValue, NewValue) // стандартный метод StringBuilder + else begin + var from := 0; + loop n do + begin + var index := Self.IndexOf(OldValue, from); + if index = -1 then exit; + Self.Remove(index, OldValue.Length); + Self.Insert(index, NewValue); + from := index + NewValue.Length; + end; + end; + Result := Self; +end; + //-------------------------------------------- //>> Методы расширения типа Func # Extension methods for Func //-------------------------------------------- @@ -15415,7 +15504,7 @@ end;} // Присваивание реализовано в PABCExtensions. Здесь не работает -var _emptyset: NewSetEmpty := new NewSetEmpty; +var _emptyset: EmptyCollection := new EmptyCollection; type SetCreatorFunctionAttribute = class(Attribute) diff --git a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs index d38a59549..af9f6eb3c 100644 --- a/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs +++ b/TreeConverter/TreeConversion/convertion_data_and_alghoritms.cs @@ -6,7 +6,9 @@ using System.Collections.Generic; using System.Linq; using PascalABCCompiler.SemanticTree; +using PascalABCCompiler.SyntaxTree; using PascalABCCompiler.TreeRealization; +using static PascalABCCompiler.SyntaxTree.SyntaxTreeBuilder; namespace PascalABCCompiler.TreeConverter { @@ -1208,36 +1210,56 @@ namespace PascalABCCompiler.TreeConverter else { // SSM 20/01/25 - Tuple -> Tuple - /*if (formal_param_type.original_generic != null + if (formal_param_type.original_generic != null && formal_param_type.original_generic.BaseFullName.StartsWith("System.Tuple`") && factparams[i].type.original_generic != null && factparams[i].type.original_generic.BaseFullName.StartsWith("System.Tuple`") && formal_param_type.instance_params.Count == factparams[i].type.instance_params.Count - && factparams[i] is IFunctionCallNode fpf - && fpf.function.name == "Create") + //&& factparams[i] is IFunctionCallNode fpf + //&& fpf.function.name == "Create" + ) { - expressions_list el = null; - function_node fn = null; - if (fpf is common_static_method_call fpf1) { - el = fpf1.parameters; - fn = fpf1.function_node; - } - else if (fpf is compiled_static_method_call fpf2) { - el = fpf2.parameters; - fn = fpf2.function_node; - } - var ccc = syntax_tree_visitor.create_constructor_call(formal_param_type, - el, factparams[i].location); + syntax_tree_visitor.contextChanger.SaveContextAndUpToGlobalLevel(); + var sl = new statement_list(); + var rettype = new semantic_type_node(formal_param_type); + + //expressions_list parameters = null; + //if (fpf is common_static_method_call fpf1) { + // parameters = fpf1.parameters; + //} + //else if (fpf is compiled_static_method_call fpf2) { + // parameters = fpf2.parameters; + //} + + var el = new expression_list(); + for (int ii = 1; ii <= formal_param_type.instance_params.Count; ii++) + el.Add(new dot_node(new ident("x"), new ident("Item" + ii.ToString(), + factparams[i].location))); + //parameters[ii-1].location))); + SyntaxTree.expression ex = new SyntaxTree.new_expr(rettype,el); + sl.Add(new SyntaxTree.assign("Result", ex)); + // Определим функцию преобразования на внешнем уровне + var fun = BuildSimpleFunctionOneParameter("_conv" + UniqueString(), "x", + new SyntaxTree.semantic_type_node(factparams[i].type), + rettype, + sl + ); + // Теперь ее надо обойти + syntax_tree_visitor.ProcessNode(fun); + // Теперь до нее доберемся + var fn = syntax_tree_visitor.context.last_created_function.sym_info as function_node; + syntax_tree_visitor.contextChanger.RestoreCurrentContext(); + //var ccc = syntax_tree_visitor.create_constructor_call(formal_param_type, + // el, factparams[i].location); //factparams[i] = ccc; possible_type_convertions ptci = new possible_type_convertions(); - var ttttt = (ccc as compiled_constructor_call).function_node; - ptci.first = new type_conversion(ttttt); + ptci.first = new type_conversion(fn); ptci.second = null; ptci.from = factparams[i].type; ptci.to = formal_param_type; tc.AddElement(ptci); return tc; - }*/ + } //issue #2161 - SSM 12.03.2020 //issue #348 diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index d0dc5755a..608c32a3f 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -15460,7 +15460,7 @@ namespace PascalABCCompiler.TreeConverter { // Отдельно для пустого множества common_namespace_function_call cnfc = expr as common_namespace_function_call; - if (cnfc.type.name == "NewSetEmpty") + if (cnfc.type.name == "EmptyCollection") { constant = new common_namespace_function_call_as_constant(expr as common_namespace_function_call, loc); return constant; @@ -15475,7 +15475,7 @@ namespace PascalABCCompiler.TreeConverter return constant; } else if (expr is common_namespace_function_call_as_constant cnfcac - && cnfcac.type.name == "NewSetEmpty") + && cnfcac.type.name == "EmptyCollection") { expr = create_constructor_call(tn, new expressions_list(), loc); constant = new common_constructor_call_as_constant(expr as common_constructor_call, loc); diff --git a/bin/Highlighting/PascalABCNET.xshd b/bin/Highlighting/PascalABCNET.xshd index 9ac52ebd1..071df0bc2 100644 --- a/bin/Highlighting/PascalABCNET.xshd +++ b/bin/Highlighting/PascalABCNET.xshd @@ -235,6 +235,7 @@ + @@ -242,6 +243,7 @@ + diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index a544854a4..052651fe7 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -105,7 +105,7 @@ type /// Представляет произвольно большое целое число BigInteger = System.Numerics.BigInteger; - + /// Представляет дату и время DateTime = System.DateTime; @@ -181,6 +181,9 @@ type /// Представляет изменяемую строку символов StringBuilder = System.Text.StringBuilder; + /// Представляет строку с эффективным изменением + faststring = StringBuilder; + /// Тип кодировки символов Encoding = System.Text.Encoding; @@ -483,7 +486,7 @@ type end;} type - NewSetEmpty = class; + EmptyCollection = class; /// Тип встроенного множества NewSet = record(IEnumerable) @@ -558,66 +561,77 @@ type begin Result._hs := new HashSet(a); end; - - static function operator implicit(ns: NewSetEmpty): NewSet; begin end; static function operator:=(var s: NewSet; st: NewSet): NewSet; // Эту функцию обязательно здесь определять begin s._hs := new HashSet(st.hs); end; + static function operator implicit(ns: EmptyCollection): NewSet; begin end; end; - NewSetEmpty = class + EmptyCollection = class public - static function operator=(s1: NewSet; s2: NewSetEmpty): boolean := s1.Count = 0; - static function operator=(s2: NewSetEmpty; s1: NewSet): boolean := s1.Count = 0; - static function operator<>(s1: NewSet; s2: NewSetEmpty): boolean := not (s1 = s2); - static function operator<>(s2: NewSetEmpty; s1: NewSet): boolean := not (s1 = s2); - static function operator>(s1: NewSet; s2: NewSetEmpty): boolean := s1.Count > 0; - static function operator>(s2: NewSetEmpty; s1: NewSet): boolean := False; - static function operator<(s1: NewSet; s2: NewSetEmpty): boolean := False; - static function operator<(s2: NewSetEmpty; s1: NewSet): boolean := s1.Count > 0; - static function operator>=(s1: NewSet; s2: NewSetEmpty): boolean := s1.Count >= 0; - static function operator>=(s2: NewSetEmpty; s1: NewSet): boolean := False; - static function operator<=(s1: NewSet; s2: NewSetEmpty): boolean := False; - static function operator<=(s2: NewSetEmpty; s1: NewSet): boolean := s1.Count >= 0; + static function operator=(s1: NewSet; s2: EmptyCollection): boolean := s1.Count = 0; + static function operator=(s2: EmptyCollection; s1: NewSet): boolean := s1.Count = 0; + static function operator<>(s1: NewSet; s2: EmptyCollection): boolean := not (s1 = s2); + static function operator<>(s2: EmptyCollection; s1: NewSet): boolean := not (s1 = s2); + static function operator>(s1: NewSet; s2: EmptyCollection): boolean := s1.Count > 0; + static function operator>(s2: EmptyCollection; s1: NewSet): boolean := False; + static function operator<(s1: NewSet; s2: EmptyCollection): boolean := False; + static function operator<(s2: EmptyCollection; s1: NewSet): boolean := s1.Count > 0; + static function operator>=(s1: NewSet; s2: EmptyCollection): boolean := s1.Count >= 0; + static function operator>=(s2: EmptyCollection; s1: NewSet): boolean := False; + static function operator<=(s1: NewSet; s2: EmptyCollection): boolean := False; + static function operator<=(s2: EmptyCollection; s1: NewSet): boolean := s1.Count >= 0; // ToDo: определить то же для массивов на будущее - static function operator+(first, second: NewSetEmpty): NewSetEmpty := new NewSetEmpty; - static function operator-(first, second: NewSetEmpty): NewSetEmpty := new NewSetEmpty; - static function operator*(first, second: NewSetEmpty): NewSetEmpty := new NewSetEmpty; - static function operator+(first: NewSetEmpty; second: array of T): NewSet; + static function operator+(first, second: EmptyCollection): EmptyCollection := new EmptyCollection; + static function operator-(first, second: EmptyCollection): EmptyCollection := new EmptyCollection; + static function operator*(first, second: EmptyCollection): EmptyCollection := new EmptyCollection; + static function operator+(first: EmptyCollection; second: array of T): NewSet; begin Result.hs.UnionWith(second); end; - static function operator+(first: array of T; second: NewSetEmpty): NewSet; + static function operator+(first: array of T; second: EmptyCollection): NewSet; begin Result.hs.UnionWith(first); end; - static function operator+(first: NewSet; second: NewSetEmpty): NewSet := first; - static function operator+(first: NewSetEmpty; second: NewSet): NewSet := second; - static function operator*(first: NewSet; second: NewSetEmpty): NewSet; begin end; - static function operator*(first: NewSetEmpty; second: NewSet): NewSet; begin end; - static function operator-(first: NewSet; second: NewSetEmpty): NewSet := first; - static function operator-(first: NewSetEmpty; second: NewSet): NewSet; begin end; + static function operator+(first: NewSet; second: EmptyCollection): NewSet := first; + static function operator+(first: EmptyCollection; second: NewSet): NewSet := second; + static function operator*(first: NewSet; second: EmptyCollection): NewSet; begin end; + static function operator*(first: EmptyCollection; second: NewSet): NewSet; begin end; + static function operator-(first: NewSet; second: EmptyCollection): NewSet := first; + static function operator-(first: EmptyCollection; second: NewSet): NewSet; begin end; - static function operator*(first: NewSetEmpty; second: array of T): NewSet; begin end; - static function operator*(first: array of T; second: NewSetEmpty): NewSet; begin end; - static function operator-(first: NewSetEmpty; second: array of T): NewSet; begin end; - static function operator-(first: array of T; second: NewSetEmpty): NewSet; + static function operator*(first: EmptyCollection; second: array of T): NewSet; begin end; + static function operator*(first: array of T; second: EmptyCollection): NewSet; begin end; + static function operator-(first: EmptyCollection; second: array of T): NewSet; begin end; + static function operator-(first: array of T; second: EmptyCollection): NewSet; begin Result.hs.UnionWith(first); end; function ToString: string; override := '{}'; function ToSet(): NewSet; begin end; - static function operator implicit(Self: NewSetEmpty): array of T; + static function operator implicit(Self: EmptyCollection): array of T; begin - Result := new T[0]; + Result := new T[0]//System.Array.Empty&; end; - static function operator implicit(Self: NewSetEmpty): HashSet; + static function operator implicit(Self: EmptyCollection): HashSet; begin Result := new HashSet; end; + static function operator implicit(Self: EmptyCollection): SortedSet; + begin + Result := new SortedSet; + end; + static function operator implicit(Self: EmptyCollection): List; + begin + Result := new List; + end; + static function operator implicit(Self: EmptyCollection): Dictionary; + begin + Result := new Dictionary; + end; end; type @@ -667,7 +681,7 @@ type end; /// Значение пустого множества -function EmptySet: NewSetEmpty; +function EmptySet: EmptyCollection; /// Генератор множества function __NewSetCreatorInternal(params a: array of T): NewSet; @@ -14689,6 +14703,81 @@ begin &to.IndexValue := Self.Count - &to.IndexValue + 1; Result := SystemSliceStringImplQuestion(Self, situation, from.IndexValue, &to.IndexValue, step, 0); end; + +//-------------------------------------------- +//>> Методы расширения типа faststring (StringBuilder) # Extension methods for faststring (StringBuilder) +//-------------------------------------------- +/// Возвращает индекс вхождения подстроки в быструю строку +function IndexOf(Self: faststring; subs: string; from: integer := 0): integer; extensionmethod; +begin + var lens := Self.Length; + var lens1 := subs.Length; + + if (from < 0) or (lens1 > lens - from) then + begin + Result := -1; + exit; + end; + + if lens1 = 0 then + begin + Result := from; + exit; + end; + + for var i := from to lens - lens1 do + begin + var found := True; + for var j := 0 to lens1 - 1 do + begin + if Self[i + j] <> subs[j + 1] then + begin + found := False; + break; + end; + end; + + if found then + begin + Result := i; + exit; + end; + end; + + Result := -1; +end; + +/// Преобразует быструю строку в последовательность символов +function ToSequence(Self: faststring): sequence of char; extensionmethod; +begin + for var i:=0 to Self.Length - 1 do + yield Self[i]; +end; + +function operator in(subs: string; s: faststring): boolean; extensionmethod; +begin + Result := s.IndexOf(subs) <> -1; +end; + +/// Замещает n вхождений указанной строки на другую строку (все при n = 0) +function Replace(Self: faststring; OldValue, NewValue: string; n: integer): faststring; extensionmethod; +begin + if n = 0 then + Self.Replace(OldValue, NewValue) // стандартный метод StringBuilder + else begin + var from := 0; + loop n do + begin + var index := Self.IndexOf(OldValue, from); + if index = -1 then exit; + Self.Remove(index, OldValue.Length); + Self.Insert(index, NewValue); + from := index + NewValue.Length; + end; + end; + Result := Self; +end; + //-------------------------------------------- //>> Методы расширения типа Func # Extension methods for Func //-------------------------------------------- @@ -15415,7 +15504,7 @@ end;} // Присваивание реализовано в PABCExtensions. Здесь не работает -var _emptyset: NewSetEmpty := new NewSetEmpty; +var _emptyset: EmptyCollection := new EmptyCollection; type SetCreatorFunctionAttribute = class(Attribute)