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