Изменена реализация метода Slice и срезов a[f,t,s]

This commit is contained in:
miks1965 2016-03-28 15:25:46 +03:00
parent 7278c5136d
commit 8d7c9fca46
9 changed files with 784 additions and 73 deletions

View file

@ -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 = "1203";
public const string Revision = "1207";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;

View file

@ -1,4 +1,4 @@
%COREVERSION%=0
%REVISION%=1203
%REVISION%=1207
%MINOR%=1
%MAJOR%=3

View file

@ -1 +1 @@
!define VERSION '3.1.0.1203'
!define VERSION '3.1.0.1207'

View file

@ -1871,7 +1871,10 @@ const
BAD_TYPE_IN_RUNTIMESIZEOF = 'Bad Type in RunTimeSizeOf';
PARAMETER_COUNT_MUST_BE_GREATER_0 = 'Параметр count должен быть > 0!!Parameter count must be > 0';
PARAMETER_COUNT_MUST_BE_GREATER_1 = 'Параметр count должен быть > 1!!Parameter count must be > 1';
PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0 = 'Параметр step не может быть равен 0!!The step parameter must be not equal to 0';
PARAMETER_STEP_MUST_BE_NOT_EQUAL_0 = 'Параметр step не может быть равен 0!!The step parameter must be not equal to 0';
PARAMETER_STEP_MUST_BE_GREATER_0 = 'Параметр step должен быть > 0!!The step parameter must be not greater than 0';
PARAMETER_FROM_OUT_OF_RANGE = 'Параметр from за пределами диапазона!!The from parameter out of bounds';
PARAMETER_TO_OUT_OF_RANGE = 'Параметр to за пределами диапазона!!The to parameter out of bounds';
// -----------------------------------------------------
// WINAPI
@ -3494,7 +3497,7 @@ end;
// -----------------------------------------------------------------------------
type
// Вспомогательный класс для генерации всех последовательностей. К сожалению, пока с object
// Вспомогательный класс для генерации всех последовательностей
SeqBase<T> = class(IEnumerable<T>,IEnumerator<T>)
public
function System.Collections.IEnumerable.GetEnumerator(): System.Collections.IEnumerator;
@ -8113,12 +8116,23 @@ begin
Result := SeqWhile(Self,v->v.Skip(size),v->v.Count>0).Select(v->v.Take(size)).Select(ss->proj(ss));
end;
function SliceSeqImpl<T>(Self: sequence of T; from,step,count: integer): sequence of T;
begin
if step <= 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_GREATER_0));
if from < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
Result := Self.Skip(from).Where((x,i)->i mod step = 0)
end;
/// Возвращает срез последовательности от номера from с шагом step
function Slice<T>(Self: sequence of T; from,step: integer): sequence of T; extensionmethod;
begin
if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0));
{if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if step<0 then
begin
if from<0 then
@ -8133,14 +8147,21 @@ begin
else
if from<=0 then
Result := Self.Where((x,i)->(i-from) mod step = 0)
else Result := Self.Skip(from).Where((x,i)->i mod step = 0);
else Result := Self.Skip(from).Where((x,i)->i mod step = 0);}
if step <= 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_GREATER_0));
if from < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
Result := Self.Skip(from).Where((x,i)->i mod step = 0)
end;
/// Возвращает срез последовательности от номера from с шагом step длины не более count
function Slice<T>(Self: sequence of T; from,step,count: integer): sequence of T; extensionmethod;
begin
if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0));
{if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if step<0 then
begin
if from<0 then
@ -8162,7 +8183,15 @@ begin
count -= abs(from+1) div step + 1;
Result := Self.Where((x,i)->(i-from) mod step = 0).Take(count)
end
else Result := Self.Skip(from).Where((x,i)->i mod step = 0).Take(count);
else Result := Self.Skip(from).Where((x,i)->i mod step = 0).Take(count);}
if step <= 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_GREATER_0));
if from < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
Result := Self.Skip(from).Where((x,i)->i mod step = 0).Take(count)
end;
// -----------------------------------------------------
@ -8183,18 +8212,145 @@ begin
Result := Self;
end;
///--
function CreateSliceFromListInternal<T>(Self: List<T>; from,step,count: integer): List<T>;
begin
Result := new List<T>(count);
var f := from;
for var i:=0 to count-1 do
begin
Result.Add(Self[f]);
f += step;
end;
end;
procedure CorrectCountForSlice(Len,from,step: integer; var count: integer);
begin
if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if count < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_GREATER_0));
if (from < 0) or (from > Len - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Len - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;
end;
///--
function SliceListImpl<T>(Self: List<T>; from,step,count: integer): List<T>;
begin
CorrectCountForSlice(Self.Count,from,step,count);
{if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Self.Count - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Self.Count - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;}
Result := CreateSliceFromListInternal(Self,from,step,count);
end;
/// Возвращает срез списка от индекса from с шагом step
function Slice<T>(Self: List<T>; from,step: integer): List<T>; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step).ToList;
Result := SliceListImpl(Self,from,step,integer.MaxValue);
end;
/// Возвращает срез списка от индекса from с шагом step длины не более count
function Slice<T>(Self: List<T>; from,step,count: integer): List<T>; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step,count).ToList;
Result := SliceListImpl(Self,from,step,count);
end;
/// Удаляет последний элемент. Если элементов нет, генерирует исключение
function RemoveLast<T>(Self: List<T>): List<T>; extensionmethod;
begin
Self.RemoveAt(Self.Count - 1);
Result := Self;
end;
///--
function CalcCountForSystemSlice(situation: integer; Len: integer; var from,&to: integer; step: integer): integer;
begin
// situation = 0 - все параметры присутствуют
// situation = 1 - from отсутствует
// situation = 2 - to отсутствует
// situation = 3 - from и to отсутствуют
if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Len - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
if (&to < -1) or (&to > Len) then
raise new ArgumentException(GetTranslation(PARAMETER_TO_OUT_OF_RANGE));
var count: integer;
if step>0 then
begin
case situation of
1: from := 0;
2: &to := Len;
3: begin
from := 0;
&to := Len;
end;
end;
var cnt := &to - from;
if cnt<=0 then
count := 0
else count := (cnt-1) div step + 1;
end
else
begin
case situation of
1: from := Len - 1;
2: &to := -1;
3: begin
from := Len - 1;
&to := -1;
end;
end;
var cnt := from - &to;
if cnt<=0 then
count := 0
else count := (cnt-1) div (-step) + 1;
end;
Result := count;
end;
///--
function SystemSliceListImpl<T>(Self: List<T>; situation: integer; from,&to: integer; step: integer := 1): List<T>;
begin
var count := CalcCountForSystemSlice(situation,Self.Count,from,&to,step);
Result := CreateSliceFromListInternal(Self,from,step,count);
end;
///--
function SystemSlice<T>(Self: List<T>; situation: integer; from,&to: integer): List<T>; extensionmethod;
begin
Result := SystemSliceListImpl(Self,situation,from,&to,1);
end;
///--
function SystemSlice<T>(Self: List<T>; situation: integer; from,&to,step: integer): List<T>; extensionmethod;
begin
Result := SystemSliceListImpl(Self,situation,from,&to,step);
end;
// -----------------------------------------------------
//>> Методы расширения типа array of T # Extension methods for array of T
@ -8290,7 +8446,7 @@ begin
Result := System.Array.FindIndex(self,p);
end;
/// Возвращает в виде массива все элементы, удовлетворяющие предикатуы
/// Возвращает в виде массива все элементы, удовлетворяющие предикату
function FindAll<T>(self: array of T; p: T->boolean): array of T; extensionmethod;
begin
Result := System.Array.FindAll(self,p);
@ -8338,18 +8494,68 @@ begin
System.Array.Sort(self,cmp);
end;
///--
function CreateSliceFromArrayInternal<T>(Self: array of T; from,step,count: integer): array of T;
begin
Result := new T[count];
var f := from;
for var i:=0 to count-1 do
begin
Result[i] := Self[f];
f += step;
end;
end;
function SliceArrayImpl<T>(Self: array of T; from,step,count: integer): array of T;
begin
{if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Self.Length - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Self.Length - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;}
CorrectCountForSlice(Self.Length,from,step,count);
Result := CreateSliceFromArrayInternal(Self,from,step,count)
end;
/// Возвращает срез массива от индекса from с шагом step
function Slice<T>(Self: array of T; from,step: integer): array of T; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step).ToArray;
Result := SliceArrayImpl(Self,from,step,integer.MaxValue);
end;
/// Возвращает срез массива от индекса from с шагом step длины не более count
function Slice<T>(Self: array of T; from,step,count: integer): array of T; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step,count).ToArray;
Result := SliceArrayImpl(Self,from,step,count);
end;
///--
function SystemSliceArrayImpl<T>(Self: array of T; situation: integer; from,&to: integer; step: integer := 1): array of T;
begin
var count := CalcCountForSystemSlice(situation,Self.Length,from,&to,step);
Result := CreateSliceFromArrayInternal(Self,from,step,count)
end;
///--
function SystemSlice<T>(Self: array of T; situation: integer; from,&to: integer): array of T; extensionmethod;
begin
Result := SystemSliceArrayImpl(Self,situation,from,&to,1);
end;
///--
function SystemSlice<T>(Self: array of T; situation: integer; from,&to,step: integer): array of T; extensionmethod;
begin
Result := SystemSliceArrayImpl(Self,situation,from,&to,step);
end;
// -----------------------------------------------------
//>> Методы расширения типа integer # Extension methods for integer
@ -8636,18 +8842,73 @@ begin
else Result := Self;
end;
///--
function CreateSliceFromStringInternal(Self: string; from,step,count: integer): string;
begin
var res := new StringBuilder(count);
for var i:=0 to count-1 do
begin
res.Append(Self[from]);
from += step;
end;
Result := res.ToString;
end;
function SliceStringImpl(Self: string; from,step,count: integer): string;
begin
{if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Self.Length - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Self.Length - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;}
CorrectCountForSlice(Self.Length,from,step,count);
Result := CreateSliceFromStringInternal(Self,from+1,step,count);
end;
/// Возвращает срез строки от индекса from с шагом step
function Slice(Self: string; from,step: integer): string; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step).JoinIntoString('');
Result := SliceStringImpl(Self,from,step,integer.MaxValue);
end;
/// Возвращает срез строки от индекса from с шагом step длины не более count
function Slice(Self: string; from,step,count: integer): string; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step,count).JoinIntoString('');
Result := SliceStringImpl(Self,from,step,count);
end;
///--
function SystemSliceStringImpl(Self: string; situation: integer; from,&to: integer; step: integer := 1): string;
begin
var fromv := from-1;
var tov := &to-1;
var count := CalcCountForSystemSlice(situation,Self.Length,fromv,tov,step);
Result := CreateSliceFromStringInternal(Self,fromv+1,step,count)
end;
///--
function SystemSlice(Self: string; situation: integer; from,&to: integer): string; extensionmethod;
begin
Result := SystemSliceStringImpl(Self,situation,from,&to,1);
end;
///--
function SystemSlice(Self: string; situation: integer; from,&to,step: integer): string; extensionmethod;
begin
Result := SystemSliceStringImpl(Self,situation,from,&to,step);
end;
//--------------------------------------------
//>> Методы расширения типа Func # Extension methods for Func
//--------------------------------------------
@ -8732,7 +8993,7 @@ end;
// -------------------------------------------
// Дополнения февраль 2016
// Добавляет поле к кортежу
{// Добавляет поле к кортежу
function Add<T1, T2, T3> (Self: (T1,T2); v: T3): (T1,T2,T3); extensionmethod;
begin
Result := (Self[0],Self[1],v);
@ -8760,7 +9021,7 @@ end;
function Add<T1, T2, T3, T4, T5, T6, T7> (Self: (T1,T2,T3,T4,T5,T6); v: T7): (T1,T2,T3,T4,T5,T6,T7); extensionmethod;
begin
Result := (Self[0],Self[1],Self[2],Self[3],Self[4],Self[5],v);
end;
end;}
{// Определяет, есть ли указанный элемент в массиве
function Contains<T>(self: array of T; x: T): boolean; extensionmethod;

View file

@ -41,7 +41,8 @@ namespace PascalABCCompiler.TreeConverter
public override void visit(SyntaxTree.var_statement defs)
{
indef = true;
ProcessNode(defs.var_def.vars); // исключаем типы - просматриваем только имена переменных
ProcessNode(defs.var_def.vars); // исключаем типы -
// просматриваем только имена переменных
indef = false;
}
}

View file

@ -18871,15 +18871,40 @@ namespace PascalABCCompiler.TreeConverter
}
}
// Это в куче мест надо. Потому что либо compiled_type_node, либо compiled_generic_instance_type_node
// compiled_type_node если в записи A<T> все типы NETовские
// compiled_generic_instance_type_node если в записи A<T> хоть один тип - паскалевский
public Type ConvertSemanticTypeNodeToNETType(type_node tn)
{
if (tn is compiled_generic_instance_type_node)
{
var tnc = (tn as compiled_generic_instance_type_node);
var itnc = tnc.original_generic as compiled_type_node;
var tt = itnc.compiled_type;
if (tt.IsGenericType)
tt = tt.GetGenericTypeDefinition();
return tt;
}
else if (tn is compiled_type_node)
{
var itnc = (tn as compiled_type_node);
var tt = itnc.compiled_type;
if (tt.IsGenericType)
tt = tt.GetGenericTypeDefinition();
return tt;
}
return null;
}
public override void visit(SyntaxTree.assign_tuple asstup)
{
// Проверить, что справа - Tuple
var expr = convert_strong(asstup.expr);
var ent = expr.type as compiled_type_node;
if (ent == null)
var t = ConvertSemanticTypeNodeToNETType(expr.type);
if (t == null)
AddError(expr.location, "TUPLE_EXPECTED");
var t = ent.compiled_type;
//if (t != typeof(System.Tuple<>))
if (!t.FullName.StartsWith("System.Tuple"))
AddError(expr.location, "TUPLE_EXPECTED");
@ -18904,6 +18929,7 @@ namespace PascalABCCompiler.TreeConverter
public override void visit(SyntaxTree.slice_expr sl)
{
// Устарело
// Преобразуется в вызов a.Slice
// from, step сохраняются, count вычисляется как count = (to-from+step-sign(step)) div step
// Для a: нужно to присвоить очень большое целое
@ -18911,16 +18937,35 @@ namespace PascalABCCompiler.TreeConverter
// Для a::step нужно использовать a.Slice(from,step)
// Для :b:step нужно закодировать from - from := -MaxInt div 2 и в методе Slice это проверить и поправить from в зависимости от знака step
// Новое
// Последовательности исключены
// Преобразуется в вызов a.SystemSlice(situation,from,to,step)
// situation = 0 - ничего не пропущено
// situation = 1 - пропущен from
// situation = 2 - пропущен to
// situation = 3 - пропущены from и to
var semvar = convert_strong(sl.v);
var semvartype = semvar.type;
var IsOrImplementsIEnumerableT = false; // проверим, является ли semvartype интерфейсом IEnumerable<T> или реализует его
// semvartype должен быть array of T, List<T> или string
var ct = semvartype as compiled_type_node;
var IsSlicedType = false; // проверим, является ли semvartype интерфейсом IEnumerable<T> или реализует его
var t = ConvertSemanticTypeNodeToNETType(semvartype);
if (t.IsArray)
IsSlicedType = true;
else if (t == typeof(System.String))
IsSlicedType = true;
else if (t.IsGenericType && t.GetGenericTypeDefinition()==typeof(System.Collections.Generic.List<>))
IsSlicedType = true;
/*var ct = semvartype as compiled_type_node;
if (ct != null && ct.compiled_type.IsGenericType && ct.compiled_type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IEnumerable<>)) // это он и есть
IsOrImplementsIEnumerableT = true;
IsSlicedType = true;
if (!IsOrImplementsIEnumerableT)
if (!IsSlicedType)
foreach (SemanticTree.ITypeNode itn in semvartype.ImplementingInterfaces) // Ищем интерфейс IEnumerable<T>
{
if (itn is compiled_generic_instance_type_node)
@ -18930,7 +18975,7 @@ namespace PascalABCCompiler.TreeConverter
if (tt == typeof(System.Collections.Generic.IEnumerable<>))
{
IsOrImplementsIEnumerableT = true;
IsSlicedType = true;
break;
}
}
@ -18944,15 +18989,44 @@ namespace PascalABCCompiler.TreeConverter
if (tt1 == typeof(System.Collections.Generic.IEnumerable<>))
{
IsOrImplementsIEnumerableT = true;
IsSlicedType = true;
break;
}
}
}
if (!IsOrImplementsIEnumerableT)
*/
if (!IsSlicedType)
AddError(get_location(sl.v), "BAD_SLICE_OBJECT");
int situation = 0;
if (sl.from == null && sl.to != null)
situation = 1;
else if (sl.from != null && sl.to == null)
situation = 2;
else if (sl.from == null && sl.to == null)
situation = 3;
var zero = new int32_const(0);
// заполняем пустые чем-нибудь
if (sl.from == null)
sl.from = zero;
if (sl.to == null)
sl.to = zero;
if (sl.step == null)
sl.step = new int32_const(1);
var el = new SyntaxTree.expression_list();
el.Add(new int32_const(situation));
el.Add(sl.from);
el.Add(sl.to);
el.Add(sl.step);
var mc = new method_call(new dot_node(sl.v, new ident("SystemSlice", sl.v.source_context), sl.v.source_context), el, sl.source_context);
visit(mc);
/*
// Ситуация from::step - вызвать Slice с двумя параметрами - пропустить вычисление и добавление count
bool SituationFromSpaceStep = (sl.from != null) && (sl.to == null) && (sl.step != null);
// Ситуация :to:step - закодировать from = -MaxInt div 2 и в Slice сделато коррекцию если step<0 !!!
@ -19017,23 +19091,25 @@ namespace PascalABCCompiler.TreeConverter
var mc = new method_call(new dot_node(sl.v, new ident("Slice", sl.v.source_context), sl.v.source_context), el, sl.source_context);
visit(mc);
*/
}
/*public SyntaxTree.question_colon_expression ConvertToQCE(dot_question_node dqn)
{
// Неверно работает. Пока не используется. Доделать
addressed_value left = dqn.left;
addressed_value right = dqn.right;
var eq = new bin_expr(left, new nil_const(), Operators.Equal, left.source_context);
var dn = new dot_node(left, right, dqn.source_context);
var q = new SyntaxTree.question_colon_expression(eq, new nil_const(), dn, dqn.source_context);
return q;
}
public override void visit(SyntaxTree.dot_question_node dqn)
{
// a?.b
var q = ConvertToQCE(dqn);
visit(q);
}*/
/*public SyntaxTree.question_colon_expression ConvertToQCE(dot_question_node dqn)
{
// Неверно работает. Пока не используется. Доделать
addressed_value left = dqn.left;
addressed_value right = dqn.right;
var eq = new bin_expr(left, new nil_const(), Operators.Equal, left.source_context);
var dn = new dot_node(left, right, dqn.source_context);
var q = new SyntaxTree.question_colon_expression(eq, new nil_const(), dn, dqn.source_context);
return q;
}
public override void visit(SyntaxTree.dot_question_node dqn)
{
// a?.b
var q = ConvertToQCE(dqn);
visit(q);
}*/
}
}

Binary file not shown.

View file

@ -2374,6 +2374,127 @@
</Node>
</Items>
</Node>
<Node Name="Slices">
<Items>
<Node Name="Slice&lt;T&gt;(Self: sequence of T">
<FileName>\PABCSystem.pas</FileName>
<Text>function Slice&lt;T&gt;(Self: sequence of T; from,step: integer): sequence of T; extensionmethod;</Text>
<OCtx>
<i Type="Method">function Slice &lt; T &gt; ( Self : sequence of T ; from , step : integer ) : sequence of T extensionmethod</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="Slice&lt;T&gt;(Self: List&lt;T&gt;">
<FileName>\PABCSystem.pas</FileName>
<Text>function Slice&lt;T&gt;(Self: List&lt;T&gt;; from,step,count: integer): List&lt;T&gt;; extensionmethod;</Text>
<OCtx>
<i Type="Method">function Slice &lt; T &gt; ( Self : List &lt; T &gt; ; from , step , count : integer ) : List &lt; T &gt; extensionmethod</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="Slice&lt;T&gt;(Self: array of T">
<FileName>\PABCSystem.pas</FileName>
<Text>function Slice&lt;T&gt;(Self: array of T; from,step: integer): array of T; extensionmethod;</Text>
<OCtx>
<i Type="Method">function Slice &lt; T &gt; ( Self : array of T ; from , step : integer ) : array of T extensionmethod</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="Slice(Self: string;">
<FileName>\PABCSystem.pas</FileName>
<Text>function Slice(Self: string; from,step: integer): string; extensionmethod;</Text>
<OCtx>
<i Type="Method">function Slice ( Self : string ; from , step : integer ) : string extensionmethod</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="CalcCountForSystemSlice">
<FileName>\PABCSystem.pas</FileName>
<Text>function CalcCountForSystemSlice(situation: integer; Len: integer; var from,&amp;to: integer; step: integer): integer;</Text>
<OCtx>
<i Type="Method">function CalcCountForSystemSlice ( situation : integer ; Len : integer ; var from , &amp;to : integer ; step : integer ) : integer</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="SliceListImpl&lt;T&gt;(Self: List&lt;T&gt;">
<FileName>\PABCSystem.pas</FileName>
<Text>function SliceListImpl&lt;T&gt;(Self: List&lt;T&gt;; from,step,count: integer): List&lt;T&gt;;</Text>
<OCtx>
<i Type="Method">function SliceListImpl &lt; T &gt; ( Self : List &lt; T &gt; ; from , step , count : integer ) : List &lt; T &gt;</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="SliceArrayImpl&lt;T&gt;(Self: array of T">
<FileName>\PABCSystem.pas</FileName>
<Text>function SliceArrayImpl&lt;T&gt;(Self: array of T; from,step,count: integer): array of T;</Text>
<OCtx>
<i Type="Method">function SliceArrayImpl &lt; T &gt; ( Self : array of T ; from , step , count : integer ) : array of T</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="SliceStringImpl(Self: string">
<FileName>\PABCSystem.pas</FileName>
<Text>function SliceStringImpl(Self: string; from,step,count: integer): string;</Text>
<OCtx>
<i Type="Method">function SliceStringImpl ( Self : string ; from , step , count : integer ) : string</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="SystemSliceListImpl">
<FileName>\PABCSystem.pas</FileName>
<Text>function SystemSliceListImpl&lt;T&gt;(Self: List&lt;T&gt;; situation: integer; from,&amp;to: integer; step: integer := 1): List&lt;T&gt;;</Text>
<OCtx>
<i Type="Method">function SystemSliceListImpl &lt; T &gt; ( Self : List &lt; T &gt; ; situation : integer ; from , &amp;to : integer ; step : integer : = 1 ) : List &lt; T &gt;</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="SystemSliceArrayImpl">
<FileName>\PABCSystem.pas</FileName>
<Text>function SystemSliceListImpl&lt;T&gt;(Self: List&lt;T&gt;; situation: integer; from,&amp;to: integer; step: integer := 1): List&lt;T&gt;;</Text>
<OCtx>
<i Type="Method">function SystemSliceListImpl &lt; T &gt; ( Self : List &lt; T &gt; ; situation : integer ; from , &amp;to : integer ; step : integer : = 1 ) : List &lt; T &gt;</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="SystemSliceStringImpl">
<FileName>\PABCSystem.pas</FileName>
<Text>function SystemSliceStringImpl(Self: string; situation: integer; from,&amp;to: integer; step: integer := 1): string;</Text>
<OCtx>
<i Type="Method">function SystemSliceStringImpl ( Self : string ; situation : integer ; from , &amp;to : integer ; step : integer : = 1 ) : string</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="CreateSliceFromArrayInternal">
<FileName>\PABCSystem.pas</FileName>
<Text>function CreateSliceFromArrayInternal&lt;T&gt;(Self: array of T; from,step,count: integer): array of T;</Text>
<OCtx>
<i Type="Method">function CreateSliceFromArrayInternal &lt; T &gt; ( Self : array of T ; from , step , count : integer ) : array of T</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
<Node Name="CreateSliceFromStringInternal">
<FileName>\PABCSystem.pas</FileName>
<Text>function CreateSliceFromStringInternal&lt;T&gt;(Self: string; from,count,step: integer): string;</Text>
<OCtx>
<i Type="Method">function CreateSliceFromStringInternal ( Self : string ; from , count , step : integer ) : string</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
</Items>
</Node>
<Node Name="read_lexem">
<FileName>\PABCSystem.pas</FileName>
<Text>function read_lexem: string;// SSM 08.03.11 - пытаюсь исправить с peekом ситуацию с вводом '1 hello'. Должно работать</Text>
@ -2497,15 +2618,6 @@
<i Type="ClassMethod">procedure Reset ( )</i>
</ICtx>
</Node>
<Node Name="Slice&lt;T&gt;(Self: sequence of T">
<FileName>\PABCSystem.pas</FileName>
<Text>function Slice&lt;T&gt;(Self: sequence of T; from,step: integer): sequence of T; extensionmethod;</Text>
<OCtx>
<i Type="Method">function Slice &lt; T &gt; ( Self : sequence of T ; from , step : integer ) : sequence of T extensionmethod</i>
<i Type="PAS_TreeNode">
</i>
</OCtx>
</Node>
</Items>
</Node>
</AspectFile>

View file

@ -1871,7 +1871,10 @@ const
BAD_TYPE_IN_RUNTIMESIZEOF = 'Bad Type in RunTimeSizeOf';
PARAMETER_COUNT_MUST_BE_GREATER_0 = 'Параметр count должен быть > 0!!Parameter count must be > 0';
PARAMETER_COUNT_MUST_BE_GREATER_1 = 'Параметр count должен быть > 1!!Parameter count must be > 1';
PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0 = 'Параметр step не может быть равен 0!!The step parameter must be not equal to 0';
PARAMETER_STEP_MUST_BE_NOT_EQUAL_0 = 'Параметр step не может быть равен 0!!The step parameter must be not equal to 0';
PARAMETER_STEP_MUST_BE_GREATER_0 = 'Параметр step должен быть > 0!!The step parameter must be not greater than 0';
PARAMETER_FROM_OUT_OF_RANGE = 'Параметр from за пределами диапазона!!The from parameter out of bounds';
PARAMETER_TO_OUT_OF_RANGE = 'Параметр to за пределами диапазона!!The to parameter out of bounds';
// -----------------------------------------------------
// WINAPI
@ -3494,7 +3497,7 @@ end;
// -----------------------------------------------------------------------------
type
// Вспомогательный класс для генерации всех последовательностей. К сожалению, пока с object
// Вспомогательный класс для генерации всех последовательностей
SeqBase<T> = class(IEnumerable<T>,IEnumerator<T>)
public
function System.Collections.IEnumerable.GetEnumerator(): System.Collections.IEnumerator;
@ -8113,12 +8116,23 @@ begin
Result := SeqWhile(Self,v->v.Skip(size),v->v.Count>0).Select(v->v.Take(size)).Select(ss->proj(ss));
end;
function SliceSeqImpl<T>(Self: sequence of T; from,step,count: integer): sequence of T;
begin
if step <= 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_GREATER_0));
if from < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
Result := Self.Skip(from).Where((x,i)->i mod step = 0)
end;
/// Возвращает срез последовательности от номера from с шагом step
function Slice<T>(Self: sequence of T; from,step: integer): sequence of T; extensionmethod;
begin
if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0));
{if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if step<0 then
begin
if from<0 then
@ -8133,14 +8147,21 @@ begin
else
if from<=0 then
Result := Self.Where((x,i)->(i-from) mod step = 0)
else Result := Self.Skip(from).Where((x,i)->i mod step = 0);
else Result := Self.Skip(from).Where((x,i)->i mod step = 0);}
if step <= 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_GREATER_0));
if from < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
Result := Self.Skip(from).Where((x,i)->i mod step = 0)
end;
/// Возвращает срез последовательности от номера from с шагом step длины не более count
function Slice<T>(Self: sequence of T; from,step,count: integer): sequence of T; extensionmethod;
begin
if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0));
{if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if step<0 then
begin
if from<0 then
@ -8162,7 +8183,15 @@ begin
count -= abs(from+1) div step + 1;
Result := Self.Where((x,i)->(i-from) mod step = 0).Take(count)
end
else Result := Self.Skip(from).Where((x,i)->i mod step = 0).Take(count);
else Result := Self.Skip(from).Where((x,i)->i mod step = 0).Take(count);}
if step <= 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_GREATER_0));
if from < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
Result := Self.Skip(from).Where((x,i)->i mod step = 0).Take(count)
end;
// -----------------------------------------------------
@ -8183,18 +8212,145 @@ begin
Result := Self;
end;
///--
function CreateSliceFromListInternal<T>(Self: List<T>; from,step,count: integer): List<T>;
begin
Result := new List<T>(count);
var f := from;
for var i:=0 to count-1 do
begin
Result.Add(Self[f]);
f += step;
end;
end;
procedure CorrectCountForSlice(Len,from,step: integer; var count: integer);
begin
if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if count < 0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_GREATER_0));
if (from < 0) or (from > Len - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Len - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;
end;
///--
function SliceListImpl<T>(Self: List<T>; from,step,count: integer): List<T>;
begin
CorrectCountForSlice(Self.Count,from,step,count);
{if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Self.Count - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Self.Count - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;}
Result := CreateSliceFromListInternal(Self,from,step,count);
end;
/// Возвращает срез списка от индекса from с шагом step
function Slice<T>(Self: List<T>; from,step: integer): List<T>; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step).ToList;
Result := SliceListImpl(Self,from,step,integer.MaxValue);
end;
/// Возвращает срез списка от индекса from с шагом step длины не более count
function Slice<T>(Self: List<T>; from,step,count: integer): List<T>; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step,count).ToList;
Result := SliceListImpl(Self,from,step,count);
end;
/// Удаляет последний элемент. Если элементов нет, генерирует исключение
function RemoveLast<T>(Self: List<T>): List<T>; extensionmethod;
begin
Self.RemoveAt(Self.Count - 1);
Result := Self;
end;
///--
function CalcCountForSystemSlice(situation: integer; Len: integer; var from,&to: integer; step: integer): integer;
begin
// situation = 0 - все параметры присутствуют
// situation = 1 - from отсутствует
// situation = 2 - to отсутствует
// situation = 3 - from и to отсутствуют
if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Len - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
if (&to < -1) or (&to > Len) then
raise new ArgumentException(GetTranslation(PARAMETER_TO_OUT_OF_RANGE));
var count: integer;
if step>0 then
begin
case situation of
1: from := 0;
2: &to := Len;
3: begin
from := 0;
&to := Len;
end;
end;
var cnt := &to - from;
if cnt<=0 then
count := 0
else count := (cnt-1) div step + 1;
end
else
begin
case situation of
1: from := Len - 1;
2: &to := -1;
3: begin
from := Len - 1;
&to := -1;
end;
end;
var cnt := from - &to;
if cnt<=0 then
count := 0
else count := (cnt-1) div (-step) + 1;
end;
Result := count;
end;
///--
function SystemSliceListImpl<T>(Self: List<T>; situation: integer; from,&to: integer; step: integer := 1): List<T>;
begin
var count := CalcCountForSystemSlice(situation,Self.Count,from,&to,step);
Result := CreateSliceFromListInternal(Self,from,step,count);
end;
///--
function SystemSlice<T>(Self: List<T>; situation: integer; from,&to: integer): List<T>; extensionmethod;
begin
Result := SystemSliceListImpl(Self,situation,from,&to,1);
end;
///--
function SystemSlice<T>(Self: List<T>; situation: integer; from,&to,step: integer): List<T>; extensionmethod;
begin
Result := SystemSliceListImpl(Self,situation,from,&to,step);
end;
// -----------------------------------------------------
//>> Методы расширения типа array of T # Extension methods for array of T
@ -8290,7 +8446,7 @@ begin
Result := System.Array.FindIndex(self,p);
end;
/// Возвращает в виде массива все элементы, удовлетворяющие предикатуы
/// Возвращает в виде массива все элементы, удовлетворяющие предикату
function FindAll<T>(self: array of T; p: T->boolean): array of T; extensionmethod;
begin
Result := System.Array.FindAll(self,p);
@ -8338,18 +8494,68 @@ begin
System.Array.Sort(self,cmp);
end;
///--
function CreateSliceFromArrayInternal<T>(Self: array of T; from,step,count: integer): array of T;
begin
Result := new T[count];
var f := from;
for var i:=0 to count-1 do
begin
Result[i] := Self[f];
f += step;
end;
end;
function SliceArrayImpl<T>(Self: array of T; from,step,count: integer): array of T;
begin
{if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Self.Length - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Self.Length - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;}
CorrectCountForSlice(Self.Length,from,step,count);
Result := CreateSliceFromArrayInternal(Self,from,step,count)
end;
/// Возвращает срез массива от индекса from с шагом step
function Slice<T>(Self: array of T; from,step: integer): array of T; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step).ToArray;
Result := SliceArrayImpl(Self,from,step,integer.MaxValue);
end;
/// Возвращает срез массива от индекса from с шагом step длины не более count
function Slice<T>(Self: array of T; from,step,count: integer): array of T; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step,count).ToArray;
Result := SliceArrayImpl(Self,from,step,count);
end;
///--
function SystemSliceArrayImpl<T>(Self: array of T; situation: integer; from,&to: integer; step: integer := 1): array of T;
begin
var count := CalcCountForSystemSlice(situation,Self.Length,from,&to,step);
Result := CreateSliceFromArrayInternal(Self,from,step,count)
end;
///--
function SystemSlice<T>(Self: array of T; situation: integer; from,&to: integer): array of T; extensionmethod;
begin
Result := SystemSliceArrayImpl(Self,situation,from,&to,1);
end;
///--
function SystemSlice<T>(Self: array of T; situation: integer; from,&to,step: integer): array of T; extensionmethod;
begin
Result := SystemSliceArrayImpl(Self,situation,from,&to,step);
end;
// -----------------------------------------------------
//>> Методы расширения типа integer # Extension methods for integer
@ -8636,18 +8842,73 @@ begin
else Result := Self;
end;
///--
function CreateSliceFromStringInternal(Self: string; from,step,count: integer): string;
begin
var res := new StringBuilder(count);
for var i:=0 to count-1 do
begin
res.Append(Self[from]);
from += step;
end;
Result := res.ToString;
end;
function SliceStringImpl(Self: string; from,step,count: integer): string;
begin
{if step = 0 then
raise new ArgumentException(GetTranslation(PARAMETER_STEP_MUST_BE_NOT_EQUAL_0));
if (from < 0) or (from > Self.Length - 1) then
raise new ArgumentException(GetTranslation(PARAMETER_FROM_OUT_OF_RANGE));
var cnt := step > 0 ? Self.Length - from : from + 1;
var cntstep := (cnt-1) div abs(step) + 1;
if count > cntstep then
count := cntstep;}
CorrectCountForSlice(Self.Length,from,step,count);
Result := CreateSliceFromStringInternal(Self,from+1,step,count);
end;
/// Возвращает срез строки от индекса from с шагом step
function Slice(Self: string; from,step: integer): string; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step).JoinIntoString('');
Result := SliceStringImpl(Self,from,step,integer.MaxValue);
end;
/// Возвращает срез строки от индекса from с шагом step длины не более count
function Slice(Self: string; from,step,count: integer): string; extensionmethod;
begin
Result := Self.AsEnumerable.Slice(from,step,count).JoinIntoString('');
Result := SliceStringImpl(Self,from,step,count);
end;
///--
function SystemSliceStringImpl(Self: string; situation: integer; from,&to: integer; step: integer := 1): string;
begin
var fromv := from-1;
var tov := &to-1;
var count := CalcCountForSystemSlice(situation,Self.Length,fromv,tov,step);
Result := CreateSliceFromStringInternal(Self,fromv+1,step,count)
end;
///--
function SystemSlice(Self: string; situation: integer; from,&to: integer): string; extensionmethod;
begin
Result := SystemSliceStringImpl(Self,situation,from,&to,1);
end;
///--
function SystemSlice(Self: string; situation: integer; from,&to,step: integer): string; extensionmethod;
begin
Result := SystemSliceStringImpl(Self,situation,from,&to,step);
end;
//--------------------------------------------
//>> Методы расширения типа Func # Extension methods for Func
//--------------------------------------------
@ -8732,7 +8993,7 @@ end;
// -------------------------------------------
// Дополнения февраль 2016
// Добавляет поле к кортежу
{// Добавляет поле к кортежу
function Add<T1, T2, T3> (Self: (T1,T2); v: T3): (T1,T2,T3); extensionmethod;
begin
Result := (Self[0],Self[1],v);
@ -8760,7 +9021,7 @@ end;
function Add<T1, T2, T3, T4, T5, T6, T7> (Self: (T1,T2,T3,T4,T5,T6); v: T7): (T1,T2,T3,T4,T5,T6,T7); extensionmethod;
begin
Result := (Self[0],Self[1],Self[2],Self[3],Self[4],Self[5],v);
end;
end;}
{// Определяет, есть ли указанный элемент в массиве
function Contains<T>(self: array of T; x: T): boolean; extensionmethod;