Слайсы

This commit is contained in:
miks1965 2016-03-11 00:33:35 +03:00
parent bbe2b15590
commit 01c82f5863
16 changed files with 485 additions and 13 deletions

View file

@ -2,7 +2,7 @@
// This CSharp output file generated by Gardens Point LEX
// Version: 1.1.3.301
// Machine: SSM
// DateTime: 09.03.2016 23:53:13
// DateTime: 10.03.2016 0:57:37
// UserName: ?????????
// GPLEX input file <ABCPascal.lex>
// GPLEX frame file <embedded resource>

View file

@ -3001,7 +3001,13 @@ variable
}
| variable tkSquareOpen expr_list tkSquareClose
{
$$ = new indexer($1 as addressed_value,$3 as expression_list, @$);
var el = $3 as expression_list; // SSM 10/03/16
if (el.expressions.Count==1 && el.expressions[0] is format_expr)
{
var fe = el.expressions[0] as format_expr;
$$ = new slice_expr($1 as addressed_value,fe.expr,fe.format1,fe.format2,fe.source_context);
}
else $$ = new indexer($1 as addressed_value,el, @$);
}
| variable tkRoundOpen optional_expr_list tkRoundClose
{

View file

@ -2,7 +2,7 @@
// GPPG version 1.3.6
// Machine: SSM
// DateTime: 09.03.2016 23:53:14
// DateTime: 10.03.2016 0:57:38
// UserName: ?????????
// Input file <D:\PascalABC.NET\!PABC_Git\Parsers\PascalABCParserNewSaushkin\ABCPascal.y>
@ -4873,7 +4873,13 @@ public partial class GPPGParser: ShiftReduceParser<PascalABCSavParser.Union, Lex
break;
case 609: // variable -> variable, tkSquareOpen, expr_list, tkSquareClose
{
CurrentSemanticValue.ex = new indexer(ValueStack[ValueStack.Depth-4].ex as addressed_value,ValueStack[ValueStack.Depth-2].stn as expression_list, CurrentLocationSpan);
var el = ValueStack[ValueStack.Depth-2].stn as expression_list; // SSM 10/03/16
if (el.expressions.Count==1 && el.expressions[0] is format_expr)
{
var fe = el.expressions[0] as format_expr;
CurrentSemanticValue.ex = new slice_expr(ValueStack[ValueStack.Depth-4].ex as addressed_value,fe.expr,fe.format1,fe.format2,fe.source_context);
}
else CurrentSemanticValue.ex = new indexer(ValueStack[ValueStack.Depth-4].ex as addressed_value,el, CurrentLocationSpan);
}
break;
case 610: // variable -> variable, tkRoundOpen, optional_expr_list, tkRoundClose

View file

@ -1057,6 +1057,11 @@ namespace PascalABCCompiler.SyntaxTree
{
DefaultVisit(_dot_question_node);
}
public virtual void visit(slice_expr _slice_expr)
{
DefaultVisit(_slice_expr);
}
}

View file

@ -1685,6 +1685,14 @@ namespace PascalABCCompiler.SyntaxTree
{
}
public virtual void pre_do_visit(slice_expr _slice_expr)
{
}
public virtual void post_do_visit(slice_expr _slice_expr)
{
}
public override void visit(syntax_tree_node _syntax_tree_node)
{
DefaultVisit(_syntax_tree_node);
@ -3489,6 +3497,17 @@ namespace PascalABCCompiler.SyntaxTree
visit(dot_question_node.right);
post_do_visit(_dot_question_node);
}
public override void visit(slice_expr _slice_expr)
{
DefaultVisit(_slice_expr);
pre_do_visit(_slice_expr);
visit(slice_expr.v);
visit(slice_expr.from);
visit(slice_expr.to);
visit(slice_expr.step);
post_do_visit(_slice_expr);
}
}

View file

@ -440,6 +440,8 @@ namespace PascalABCCompiler.SyntaxTree
return new uses_closure();
case 209:
return new dot_question_node();
case 210:
return new slice_expr();
}
return null;
}
@ -2335,7 +2337,7 @@ namespace PascalABCCompiler.SyntaxTree
public void read_format_expr(format_expr _format_expr)
{
read_addressed_value(_format_expr);
read_expression(_format_expr);
_format_expr.expr = _read_node() as expression;
_format_expr.format1 = _read_node() as expression;
_format_expr.format2 = _read_node() as expression;
@ -3733,6 +3735,21 @@ namespace PascalABCCompiler.SyntaxTree
_dot_question_node.right = _read_node() as addressed_value;
}
public void visit(slice_expr _slice_expr)
{
read_slice_expr(_slice_expr);
}
public void read_slice_expr(slice_expr _slice_expr)
{
read_dereference(_slice_expr);
_slice_expr.v = _read_node() as addressed_value;
_slice_expr.from = _read_node() as expression;
_slice_expr.to = _read_node() as expression;
_slice_expr.step = _read_node() as expression;
}
}

View file

@ -3414,7 +3414,7 @@ namespace PascalABCCompiler.SyntaxTree
public void write_format_expr(format_expr _format_expr)
{
write_addressed_value(_format_expr);
write_expression(_format_expr);
if (_format_expr.expr == null)
{
bw.Write((byte)0);
@ -5860,6 +5860,54 @@ namespace PascalABCCompiler.SyntaxTree
}
}
public void visit(slice_expr _slice_expr)
{
bw.Write((Int16)210);
write_slice_expr(_slice_expr);
}
public void write_slice_expr(slice_expr _slice_expr)
{
write_dereference(_slice_expr);
if (_slice_expr.v == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_slice_expr.v.visit(this);
}
if (_slice_expr.from == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_slice_expr.from.visit(this);
}
if (_slice_expr.to == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_slice_expr.to.visit(this);
}
if (_slice_expr.step == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_slice_expr.step.visit(this);
}
}
}

View file

@ -16026,7 +16026,7 @@ namespace PascalABCCompiler.SyntaxTree
///expr:1:2
///</summary>
[Serializable]
public partial class format_expr : addressed_value
public partial class format_expr : expression
{
///<summary>
@ -27675,6 +27675,216 @@ namespace PascalABCCompiler.SyntaxTree
}
///<summary>
///
///</summary>
[Serializable]
public partial class slice_expr : dereference
{
///<summary>
///Конструктор без параметров.
///</summary>
public slice_expr()
{
}
///<summary>
///Конструктор с параметрами.
///</summary>
public slice_expr(addressed_value _v,expression _from,expression _to,expression _step)
{
this._v=_v;
this._from=_from;
this._to=_to;
this._step=_step;
}
///<summary>
///Конструктор с параметрами.
///</summary>
public slice_expr(addressed_value _v,expression _from,expression _to,expression _step,SourceContext sc)
{
this._v=_v;
this._from=_from;
this._to=_to;
this._step=_step;
source_context = sc;
}
///<summary>
///Конструктор с параметрами.
///</summary>
public slice_expr(addressed_value _dereferencing_value,addressed_value _v,expression _from,expression _to,expression _step)
{
this._dereferencing_value=_dereferencing_value;
this._v=_v;
this._from=_from;
this._to=_to;
this._step=_step;
}
///<summary>
///Конструктор с параметрами.
///</summary>
public slice_expr(addressed_value _dereferencing_value,addressed_value _v,expression _from,expression _to,expression _step,SourceContext sc)
{
this._dereferencing_value=_dereferencing_value;
this._v=_v;
this._from=_from;
this._to=_to;
this._step=_step;
source_context = sc;
}
protected addressed_value _v;
protected expression _from;
protected expression _to;
protected expression _step;
///<summary>
///
///</summary>
public addressed_value v
{
get
{
return _v;
}
set
{
_v=value;
}
}
///<summary>
///
///</summary>
public expression from
{
get
{
return _from;
}
set
{
_from=value;
}
}
///<summary>
///
///</summary>
public expression to
{
get
{
return _to;
}
set
{
_to=value;
}
}
///<summary>
///
///</summary>
public expression step
{
get
{
return _step;
}
set
{
_step=value;
}
}
///<summary>
///Свойство для получения количества всех подузлов без элементов поля типа List
///</summary>
public override Int32 subnodes_without_list_elements_count
{
get
{
return 5;
}
}
///<summary>
///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List
///</summary>
public override Int32 subnodes_count
{
get
{
return 5;
}
}
///<summary>
///Индексатор для получения всех подузлов
///</summary>
public override syntax_tree_node this[Int32 ind]
{
get
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
switch(ind)
{
case 0:
return dereferencing_value;
case 1:
return v;
case 2:
return from;
case 3:
return to;
case 4:
return step;
}
return null;
}
set
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
switch(ind)
{
case 0:
dereferencing_value = (addressed_value)value;
break;
case 1:
v = (addressed_value)value;
break;
case 2:
from = (expression)value;
break;
case 3:
to = (expression)value;
break;
case 4:
step = (expression)value;
break;
}
}
}
///<summary>
///Метод для обхода дерева посетителем
///</summary>
///<param name="visitor">Объект-посетитель.</param>
///<returns>Return value is void</returns>
public override void visit(IVisitor visitor)
{
visitor.visit(this);
}
}
}

View file

@ -1264,6 +1264,12 @@ namespace PascalABCCompiler.SyntaxTree
///<param name="_dot_question_node">Node to visit</param>
///<returns> Return value is void </returns>
void visit(dot_question_node _dot_question_node);
///<summary>
///Method to visit slice_expr.
///</summary>
///<param name="_slice_expr">Node to visit</param>
///<returns> Return value is void </returns>
void visit(slice_expr _slice_expr);
}

Binary file not shown.

View file

@ -15598,7 +15598,22 @@ namespace PascalABCCompiler.TreeConverter
AddError(new CanNotAssignToReadOnlyElement(to.location,node_type));
}
expression_node from = convert_strong(_assign.from);
//expression_node from = convert_strong(_assign.from);
/// SSM исправление Саушкина 10.03.16
expression_node from;
var fromAsLambda = _assign.from as function_lambda_definition;
if (fromAsLambda != null)
{
var lambdaVisitMode = fromAsLambda.lambda_visit_mode;
fromAsLambda.lambda_visit_mode = LambdaVisitMode.VisitForAdvancedMethodCallProcessing;
from = convert_strong(_assign.from);
fromAsLambda.lambda_visit_mode = lambdaVisitMode;
}
else
{
from = convert_strong(_assign.from);
}
/// end
if (stflambda.Count>0) // мы находимся внутри лямбды - возможно, вложенной
{
@ -18836,7 +18851,94 @@ namespace PascalABCCompiler.TreeConverter
visit(st);
}
/*public SyntaxTree.question_colon_expression ConvertToQCE(dot_question_node dqn)
public override void visit(SyntaxTree.slice_expr sl)
{
var semvar = convert_strong(sl.v);
var semvartype = semvar.type;
var IsOrImplementsIEnumerableT = false; // проверим, является ли semvartype интерфейсом IEnumerable<T> или реализует его
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;
if (!IsOrImplementsIEnumerableT)
foreach (SemanticTree.ITypeNode itn in semvartype.ImplementingInterfaces) // Ищем интерфейс IEnumerable<T>
{
if (itn is compiled_generic_instance_type_node)
{
var itnc = (itn as compiled_generic_instance_type_node);
var tt = (itnc.original_generic as compiled_type_node).compiled_type;
if (tt == typeof(System.Collections.Generic.IEnumerable<>))
{
IsOrImplementsIEnumerableT = true;
break;
}
}
else if (itn is compiled_type_node)
{
var itnc = (itn as compiled_type_node);
var tt = itnc.compiled_type;
if (!tt.IsGenericType)
continue;
var tt1 = tt.GetGenericTypeDefinition();
if (tt1 == typeof(System.Collections.Generic.IEnumerable<>))
{
IsOrImplementsIEnumerableT = true;
break;
}
}
}
if (!IsOrImplementsIEnumerableT)
AddError(get_location(sl.v), "BAD_SLICE_OBJECT");
var semfrom = convert_strong(sl.from);
convertion_data_and_alghoritms.check_convert_type(semfrom, SystemLibrary.SystemLibrary.integer_type, get_location(sl.from));
var synfrom = new SyntaxTree.semantic_addr_value(semfrom);
var int1 = new int32_const(1);
var el = new SyntaxTree.expression_list();
if (semvartype == SystemLibrary.SystemLibrary.string_type) // Сдвинуть from на 1
el.Add(new bin_expr(synfrom, int1, Operators.Minus));
else el.Add(synfrom);
SyntaxTree.expression synstep;
if (sl.step != null)
{
var semstep = convert_strong(sl.step);
convertion_data_and_alghoritms.check_convert_type(semstep, SystemLibrary.SystemLibrary.integer_type, get_location(sl.step));
synstep = new SyntaxTree.semantic_addr_value(semstep);
}
else
{
synstep = int1;
}
el.Add(synstep);
var semto = convert_strong(sl.to);
convertion_data_and_alghoritms.check_convert_type(semto, SystemLibrary.SystemLibrary.integer_type, get_location(sl.to));
var synto = new SyntaxTree.semantic_addr_value(semto);
// count = (abs(to-from)-1) div abs(step) + 1 - нет
// count = (to-from+step-1) div step
SyntaxTree.expression ex = new bin_expr(synto, synfrom, Operators.Minus);
//ex = new method_call(new ident("abs"), new expression_list(ex));
//ex = new bin_expr(ex, absstep, Operators.IntegerDivision);
SyntaxTree.expression signstep = new method_call(new ident("sign"), new expression_list(synstep));
ex = new bin_expr(ex, synstep, Operators.Plus);
ex = new bin_expr(ex, signstep, Operators.Minus);
ex = new bin_expr(ex, synstep, Operators.IntegerDivision);
el.Add(ex);
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;

Binary file not shown.

View file

@ -2497,6 +2497,15 @@
<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

@ -1868,6 +1868,7 @@ 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';
// -----------------------------------------------------
// WINAPI
@ -8046,13 +8047,52 @@ end;
/// Возвращает срез последовательности от номера from с шагом step
function Slice<T>(Self: sequence of T; from,step: integer): sequence of T; extensionmethod;
begin
Result := Self.Skip(from).Where((x,i)->i mod step = 0);
if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0));
if step<0 then
begin
if from<0 then
Result := Self.Take(0)
else
begin
step := -step;
var bb := from mod step;
Result := Self.Skip(bb).Where((x,i)->(i mod step = 0) and (i<=from-bb)).Reverse;
end;
end
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);
end;
/// Возвращает срез последовательности от номера from с шагом step длины не более count
function Slice<T>(Self: sequence of T; from,step,count: integer): sequence of T; extensionmethod;
begin
Result := Self.Skip(from).Where((x,i)->i mod step = 0).Take(count);
if step=0 then
raise new ArgumentException(GetTranslation(PARAMETER_COUNT_MUST_BE_NOT_EQUAL_0));
if step<0 then
begin
if from<0 then
Result := Self.Take(0)
else
begin
step := -step;
var bb := from - (count - 1)*step;
if bb<0 then
bb := bb mod step;
if bb < 0 then
bb += step;
Result := Self.Skip(bb).Where((x,i)->(i mod step = 0) and (i<=from-bb)).Reverse;
end;
end
else
if from<0 then
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);
end;
// -----------------------------------------------------

View file

@ -3,4 +3,6 @@ CAN_NOT_READ=Can not read data of this type
TUPLE_EXPECTED=Tuple expected
TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMRNT=Too many elements on the left side of tuple assignment
ONLY_BASE_ASSIGNMENT_FOR_TUPLE=Tuple allows only base assignment :=
TUPLE_TYPE_ERROR=Bad element in Tuple type
TUPLE_TYPE_ERROR=Bad element in Tuple type
INTEGER_VALUE_EXPECTED=Integer value expected
BAD_SLICE_OBJECT=Slices are allowed for strings, dynamic arrays, lists and sequences only

View file

@ -3,4 +3,6 @@ CAN_NOT_READ=
TUPLE_EXPECTED=Ожидался кортеж
TOO_MANY_ELEMENTS_ON_LEFT_SIDE_OF_TUPLE_ASSIGNMRNT=Слишком много элементов в левой части при присваивании кортежа
ONLY_BASE_ASSIGNMENT_FOR_TUPLE=Для кортежа допустимо только обычное присваивание :=
TUPLE_TYPE_ERROR=Ошибочная конструкция при построении типа кортежа
TUPLE_TYPE_ERROR=Ошибочная конструкция при построении типа кортежа
INTEGER_VALUE_EXPECTED=Ожидалось значение целого типа
BAD_SLICE_OBJECT=Срезы допустимы только для строк, динамических массивов, списков и последовательностей