diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index 3066d4b98..64c599806 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "1"; public const string Build = "0"; - public const string Revision = "1270"; + public const string Revision = "1271"; 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 754666808..817319209 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ -%MINOR%=1 -%REVISION%=1270 %COREVERSION%=0 +%REVISION%=1271 +%MINOR%=1 %MAJOR%=3 diff --git a/PascalABCNET.axml b/PascalABCNET.axml index 56741fd2e..91405ebfd 100644 --- a/PascalABCNET.axml +++ b/PascalABCNET.axml @@ -770,6 +770,28 @@ + + \Yield\SyntaxVisitors\YieldVisitors\ProcessYieldsCapturedVars.cs + public override void visit(procedure_definition pd) + + public override void visit ( procedure_definition pd ) + public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor + namespace SyntaxVisitors + + + + + + \Yield\YieldConversionSyntax\YieldDesugarSyntaxTreeConverter.cs + root.visit(new ProcessYieldCapturedVarsVisitor()); + + public syntax_tree_node Convert ( syntax_tree_node root ) + public class YieldDesugarSyntaxTreeConverter : ISyntaxTreeConverter + namespace YieldDesugarSyntaxTreeConverter + + + + @@ -787,7 +809,7 @@ \yield\syntaxvisitors\yieldvisitors\processyieldscapturedvars.cs type_declarations GenClassesForYield(procedure_definition pd, - type_declarations GenClassesForYield ( procedure_definition pd , IEnumerable < var_def_statement > fields , IDictionary < string , string > localsMap , IDictionary < string , string > formalParamsMap , IDictionary < var_def_statement , var_def_statement > localsCloneMap ) + type_declarations GenClassesForYield ( procedure_definition pd , IEnumerable < var_def_statement > fields , IDictionary < string , string > localsMap , IDictionary < string , string > formalParamsMap ) public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor namespace SyntaxVisitors @@ -796,17 +818,6 @@ - - \Yield\YieldConversionSyntax\YieldDesugarSyntaxTreeConverter.cs - root.visit(new ProcessYieldCapturedVarsVisitor()); - - public syntax_tree_node Convert ( syntax_tree_node root ) - public class YieldDesugarSyntaxTreeConverter : ISyntaxTreeConverter - namespace YieldDesugarSyntaxTreeConverter - - - - \TreeConverter\TreeConversion\syntax_tree_visitor.cs string Consts__Self = YieldHelpers.YieldConsts.Self; @@ -822,7 +833,7 @@ \yield\syntaxvisitors\yieldvisitors\processyieldscapturedvars.cs function_header nfh = ObjectCopier.Clone(fh); - type_declarations GenClassesForYield ( procedure_definition pd , IEnumerable < var_def_statement > fields , IDictionary < string , string > localsMap , IDictionary < string , string > formalParamsMap , IDictionary < var_def_statement , var_def_statement > localsCloneMap ) + type_declarations GenClassesForYield ( procedure_definition pd , IEnumerable < var_def_statement > fields , IDictionary < string , string > localsMap , IDictionary < string , string > formalParamsMap ) public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor namespace SyntaxVisitors @@ -844,7 +855,7 @@ \yield\syntaxvisitors\yieldvisitors\processyieldscapturedvars.cs //InsertHelperMethod(pd, pdCloned); // SSM 13.07.16 - вызов этого метода можно не добавлять - private void CreateLocalVariablesTypeProxies ( procedure_definition pd , out IEnumerable < var_def_statement > localsClonesCollection ) + private void CreateErrorCheckerHelper ( procedure_definition pd ) public class ProcessYieldCapturedVarsVisitor : BaseChangeVisitor namespace SyntaxVisitors @@ -1011,8 +1022,30 @@ + + \Yield\SyntaxVisitors\YieldVisitors\MarkMethodHasYieldVisitor.cs + if (pd.has_yield) // SSM bug fix #219 + + public override void visit ( procedure_definition pd ) + public class MarkMethodHasYieldAndCheckSomeErrorsVisitor : WalkingVisitorNew + namespace SyntaxVisitors + + + + + + \Yield\SyntaxVisitors\YieldVisitors\MarkMethodHasYieldVisitor.cs + if (id.name.ToLower() == "result") + + public override void visit ( ident id ) + public class MarkMethodHasYieldVisitor : WalkingVisitorNew + namespace SyntaxVisitors + + + + \ No newline at end of file diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index 7c9c94a70..2e9e82b97 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.1.0.1270' +!define VERSION '3.1.0.1271' diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index a2f55d87a..73c47c0e7 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -1270,6 +1270,10 @@ procedure Str(s1: string; var s: string); function Pos(subs, s: string; from: integer := 1): integer; /// Возвращает позицию подстроки subs в строке s начиная с позиции from. Если не найдена, возвращает 0 function PosEx(subs, s: string; from: integer := 1): integer; +/// Возвращает позицию последнего вхождения подстроки subs в строке s. Если не найдена, возвращает 0 +function LastPos(subs, s: string): integer; +/// Возвращает позицию последнего вхождения подстроки subs в строке s начиная с позиции from. Если не найдена, возвращает 0 +function LastPos(subs, s: string; from: integer): integer; /// Возвращает длину строки function Length(s: string): integer; /// Устанавливает длину строки s равной n @@ -7178,6 +7182,21 @@ begin else Result := s.IndexOf(subs, from - 1) + 1; end; +function LastPos(subs, s: string): integer; +begin + if (subs = nil) or (subs.Length = 0) then + Result := 0 + else Result := s.LastIndexOf(subs, s.Length - 1) + 1; +end; + +function LastPos(subs, s: string; from: integer): integer; +begin + if (subs = nil) or (subs.Length = 0) then + Result := 0 + else Result := s.LastIndexOf(subs, from - 1) + 1; +end; + + function Length(s: string): integer; begin if s <> nil then @@ -8448,10 +8467,10 @@ begin end; /// Находит первую пару подряд идущих одинаковых элементов и возвращает индекс первого элемента пары. Если не найден, возвращается -1 -function AdjacentFind(Self: array of T): integer; extensionmethod; +function AdjacentFind(Self: array of T; start: integer := 0): integer; extensionmethod; begin Result := -1; - for var i:=0 to Self.Length-2 do + for var i:=start to Self.Length-2 do if Self[i]=Self[i+1] then begin Result := i; @@ -8459,12 +8478,24 @@ begin end; end; -/// Возвращает индекс первого минимального элемента -function IndexMin(Self: array of T): integer; extensionmethod; where T: System.IComparable; +/// Находит первую пару подряд идущих одинаковых элементов, используя функцию сравнения eq, и возвращает индекс первого элемента пары. Если не найден, возвращается -1 +function AdjacentFind(Self: array of T; eq: (T,T)->boolean; start: integer := 0): integer; extensionmethod; begin - var min := Self[0]; - Result := 0; - for var i:=1 to Self.Length-1 do + Result := -1; + for var i:=start to Self.Length-2 do + if eq(Self[i],Self[i+1]) then + begin + Result := i; + exit; + end; +end; + +/// Возвращает индекс первого минимального элемента начиная с позиции start +function IndexMin(Self: array of T; start: integer := 0): integer; extensionmethod; where T: System.IComparable; +begin + var min := Self[start]; + Result := start; + for var i:=start+1 to Self.Length-1 do if Self[i].CompareTo(min)<0 then begin Result := i; @@ -8485,6 +8516,45 @@ begin end; end; +/// Возвращает индекс первого максимального элемента начиная с позиции start +function IndexMax(self: array of T; start: integer): integer; extensionmethod; where T: System.IComparable; +begin + var max := Self[start]; + Result := start; + for var i:=start+1 to Self.Length-1 do + if Self[i].CompareTo(max)>0 then + begin + Result := i; + max := Self[i]; + end; +end; + +/// Возвращает индекс последнего минимального элемента +function LastIndexMin(Self: array of T): integer; extensionmethod; where T: System.IComparable; +begin + var min := Self[Self.Length-1]; + Result := Self.Length-1; + for var i:=Self.Length-2 downto 0 do + if Self[i].CompareTo(min)<0 then + begin + Result := i; + min := Self[i]; + end; +end; + +/// Возвращает индекс последнего минимального элемента начиная с позиции start +function LastIndexMin(Self: array of T; start: integer): integer; extensionmethod; where T: System.IComparable; +begin + var min := Self[start]; + Result := start; + for var i:=start-1 downto 0 do + if Self[i].CompareTo(min)<0 then + begin + Result := i; + min := Self[i]; + end; +end; + /// Заменяет в массиве все вхождения одного значения на другое procedure Replace(Self: array of T; oldValue,newValue: T); extensionmethod; begin @@ -8524,6 +8594,12 @@ begin Result := System.Array.FindIndex(self,p); end; +/// Выполняет поиск индекса первого элемента в массиве, удовлетворяющего предикату, начиная с индекса start. Если не найден, возвращается -1 +function FindIndex(self: array of T; start: integer; p: T->boolean): integer; extensionmethod; +begin + Result := System.Array.FindIndex(self,start,p); +end; + /// Возвращает в виде массива все элементы, удовлетворяющие предикату function FindAll(self: array of T; p: T->boolean): array of T; extensionmethod; begin @@ -8542,18 +8618,36 @@ begin Result := System.Array.FindLastIndex(self,p); end; +/// Выполняет поиск индекса последнего элемента в массиве, удовлетворяющего предикату, начиная с индекса start. Если не найден, возвращается нулевое значение соответствующего типа +function FindLastIndex(self: array of T; start: integer; p: T->boolean): integer; extensionmethod; +begin + Result := System.Array.FindLastIndex(self,start,p); +end; + /// Возвращает индекс первого вхождения элемента или -1 если элемент не найден function IndexOf(self: array of T; x: T): integer; extensionmethod; begin Result := System.Array.IndexOf(self,x); end; +/// Возвращает индекс первого вхождения элемента начиная с индекса start или -1 если элемент не найден +function IndexOf(self: array of T; x: T; start: integer): integer; extensionmethod; +begin + Result := System.Array.IndexOf(self,x,start); +end; + /// Возвращает индекс последнего вхождения элемента или -1 если элемент не найден function LastIndexOf(self: array of T; x: T): integer; extensionmethod; begin Result := System.Array.LastIndexOf(self,x); end; +/// Возвращает индекс последнего вхождения элемента начиная с индекса start или -1 если элемент не найден +function LastIndexOf(self: array of T; x: T; start: integer): integer; extensionmethod; +begin + Result := System.Array.LastIndexOf(self,x,start); +end; + /// Меняет размер массива procedure Resize(self: array of T; x: integer); extensionmethod; begin diff --git a/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs index e7ad94566..f6683df0c 100644 --- a/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs +++ b/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs @@ -10,7 +10,7 @@ using PascalABCCompiler.Errors; namespace SyntaxVisitors { - public class MarkMethodHasYieldVisitor : WalkingVisitorNew + public class MarkMethodHasYieldAndCheckSomeErrorsVisitor : WalkingVisitorNew { private bool HasYields = false; private procedure_definition CurrentMethod = null; @@ -48,6 +48,19 @@ namespace SyntaxVisitors base.visit(pd); pd.has_yield = HasYields; + if (pd.has_yield) // SSM bug fix #219 + { + var ee = pd.proc_body as block; + if (ee != null) + { + var FirstTypeDeclaration = ee.defs.DescendantNodes().OfType().First(); + if (FirstTypeDeclaration != null) + { + throw new SyntaxError("Функции с yield не могут содержать локальные определения типов", "", FirstTypeDeclaration.source_context, FirstTypeDeclaration); + } + } + } + var innerPds = pd.DescendantNodes().OfType(); if (pd.has_yield && innerPds.Count() > 0 diff --git a/Yield/YieldConversionSyntax/YieldDesugarSyntaxTreeConverter.cs b/Yield/YieldConversionSyntax/YieldDesugarSyntaxTreeConverter.cs index 52e36e6d4..8317d002a 100644 --- a/Yield/YieldConversionSyntax/YieldDesugarSyntaxTreeConverter.cs +++ b/Yield/YieldConversionSyntax/YieldDesugarSyntaxTreeConverter.cs @@ -24,7 +24,7 @@ namespace YieldDesugarSyntaxTreeConverter public ExecutionOrder ExecutionOrder { get; set; } public syntax_tree_node Convert(syntax_tree_node root) { - root.visit(new MarkMethodHasYieldVisitor()); + root.visit(new MarkMethodHasYieldAndCheckSomeErrorsVisitor()); root.visit(new ProcessYieldCapturedVarsVisitor()); #if DEBUG diff --git a/bin/Lib/PABCRtl.dll b/bin/Lib/PABCRtl.dll index 2547fa8e1..738b7c7b2 100644 Binary files a/bin/Lib/PABCRtl.dll and b/bin/Lib/PABCRtl.dll differ diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index a2f55d87a..73c47c0e7 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -1270,6 +1270,10 @@ procedure Str(s1: string; var s: string); function Pos(subs, s: string; from: integer := 1): integer; /// Возвращает позицию подстроки subs в строке s начиная с позиции from. Если не найдена, возвращает 0 function PosEx(subs, s: string; from: integer := 1): integer; +/// Возвращает позицию последнего вхождения подстроки subs в строке s. Если не найдена, возвращает 0 +function LastPos(subs, s: string): integer; +/// Возвращает позицию последнего вхождения подстроки subs в строке s начиная с позиции from. Если не найдена, возвращает 0 +function LastPos(subs, s: string; from: integer): integer; /// Возвращает длину строки function Length(s: string): integer; /// Устанавливает длину строки s равной n @@ -7178,6 +7182,21 @@ begin else Result := s.IndexOf(subs, from - 1) + 1; end; +function LastPos(subs, s: string): integer; +begin + if (subs = nil) or (subs.Length = 0) then + Result := 0 + else Result := s.LastIndexOf(subs, s.Length - 1) + 1; +end; + +function LastPos(subs, s: string; from: integer): integer; +begin + if (subs = nil) or (subs.Length = 0) then + Result := 0 + else Result := s.LastIndexOf(subs, from - 1) + 1; +end; + + function Length(s: string): integer; begin if s <> nil then @@ -8448,10 +8467,10 @@ begin end; /// Находит первую пару подряд идущих одинаковых элементов и возвращает индекс первого элемента пары. Если не найден, возвращается -1 -function AdjacentFind(Self: array of T): integer; extensionmethod; +function AdjacentFind(Self: array of T; start: integer := 0): integer; extensionmethod; begin Result := -1; - for var i:=0 to Self.Length-2 do + for var i:=start to Self.Length-2 do if Self[i]=Self[i+1] then begin Result := i; @@ -8459,12 +8478,24 @@ begin end; end; -/// Возвращает индекс первого минимального элемента -function IndexMin(Self: array of T): integer; extensionmethod; where T: System.IComparable; +/// Находит первую пару подряд идущих одинаковых элементов, используя функцию сравнения eq, и возвращает индекс первого элемента пары. Если не найден, возвращается -1 +function AdjacentFind(Self: array of T; eq: (T,T)->boolean; start: integer := 0): integer; extensionmethod; begin - var min := Self[0]; - Result := 0; - for var i:=1 to Self.Length-1 do + Result := -1; + for var i:=start to Self.Length-2 do + if eq(Self[i],Self[i+1]) then + begin + Result := i; + exit; + end; +end; + +/// Возвращает индекс первого минимального элемента начиная с позиции start +function IndexMin(Self: array of T; start: integer := 0): integer; extensionmethod; where T: System.IComparable; +begin + var min := Self[start]; + Result := start; + for var i:=start+1 to Self.Length-1 do if Self[i].CompareTo(min)<0 then begin Result := i; @@ -8485,6 +8516,45 @@ begin end; end; +/// Возвращает индекс первого максимального элемента начиная с позиции start +function IndexMax(self: array of T; start: integer): integer; extensionmethod; where T: System.IComparable; +begin + var max := Self[start]; + Result := start; + for var i:=start+1 to Self.Length-1 do + if Self[i].CompareTo(max)>0 then + begin + Result := i; + max := Self[i]; + end; +end; + +/// Возвращает индекс последнего минимального элемента +function LastIndexMin(Self: array of T): integer; extensionmethod; where T: System.IComparable; +begin + var min := Self[Self.Length-1]; + Result := Self.Length-1; + for var i:=Self.Length-2 downto 0 do + if Self[i].CompareTo(min)<0 then + begin + Result := i; + min := Self[i]; + end; +end; + +/// Возвращает индекс последнего минимального элемента начиная с позиции start +function LastIndexMin(Self: array of T; start: integer): integer; extensionmethod; where T: System.IComparable; +begin + var min := Self[start]; + Result := start; + for var i:=start-1 downto 0 do + if Self[i].CompareTo(min)<0 then + begin + Result := i; + min := Self[i]; + end; +end; + /// Заменяет в массиве все вхождения одного значения на другое procedure Replace(Self: array of T; oldValue,newValue: T); extensionmethod; begin @@ -8524,6 +8594,12 @@ begin Result := System.Array.FindIndex(self,p); end; +/// Выполняет поиск индекса первого элемента в массиве, удовлетворяющего предикату, начиная с индекса start. Если не найден, возвращается -1 +function FindIndex(self: array of T; start: integer; p: T->boolean): integer; extensionmethod; +begin + Result := System.Array.FindIndex(self,start,p); +end; + /// Возвращает в виде массива все элементы, удовлетворяющие предикату function FindAll(self: array of T; p: T->boolean): array of T; extensionmethod; begin @@ -8542,18 +8618,36 @@ begin Result := System.Array.FindLastIndex(self,p); end; +/// Выполняет поиск индекса последнего элемента в массиве, удовлетворяющего предикату, начиная с индекса start. Если не найден, возвращается нулевое значение соответствующего типа +function FindLastIndex(self: array of T; start: integer; p: T->boolean): integer; extensionmethod; +begin + Result := System.Array.FindLastIndex(self,start,p); +end; + /// Возвращает индекс первого вхождения элемента или -1 если элемент не найден function IndexOf(self: array of T; x: T): integer; extensionmethod; begin Result := System.Array.IndexOf(self,x); end; +/// Возвращает индекс первого вхождения элемента начиная с индекса start или -1 если элемент не найден +function IndexOf(self: array of T; x: T; start: integer): integer; extensionmethod; +begin + Result := System.Array.IndexOf(self,x,start); +end; + /// Возвращает индекс последнего вхождения элемента или -1 если элемент не найден function LastIndexOf(self: array of T; x: T): integer; extensionmethod; begin Result := System.Array.LastIndexOf(self,x); end; +/// Возвращает индекс последнего вхождения элемента начиная с индекса start или -1 если элемент не найден +function LastIndexOf(self: array of T; x: T; start: integer): integer; extensionmethod; +begin + Result := System.Array.LastIndexOf(self,x,start); +end; + /// Меняет размер массива procedure Resize(self: array of T; x: integer); extensionmethod; begin