diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs index 2928d91eb..ed2749003 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs @@ -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 // GPLEX frame file diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.y b/Parsers/PascalABCParserNewSaushkin/ABCPascal.y index 3b8461e05..cb9b18e65 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.y +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.y @@ -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 { diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs index 12b6723d8..6f7e7f832 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs @@ -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 @@ -4873,7 +4873,13 @@ public partial class GPPGParser: ShiftReduceParser 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 diff --git a/SyntaxTree/tree/AbstractVisitor.cs b/SyntaxTree/tree/AbstractVisitor.cs index f8d79d6d6..8f724896a 100644 --- a/SyntaxTree/tree/AbstractVisitor.cs +++ b/SyntaxTree/tree/AbstractVisitor.cs @@ -1057,6 +1057,11 @@ namespace PascalABCCompiler.SyntaxTree { DefaultVisit(_dot_question_node); } + + public virtual void visit(slice_expr _slice_expr) + { + DefaultVisit(_slice_expr); + } } diff --git a/SyntaxTree/tree/HierarchyVisitor.cs b/SyntaxTree/tree/HierarchyVisitor.cs index 7f97f337c..ff05efad0 100644 --- a/SyntaxTree/tree/HierarchyVisitor.cs +++ b/SyntaxTree/tree/HierarchyVisitor.cs @@ -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); + } } diff --git a/SyntaxTree/tree/SyntaxTreeStreamReader.cs b/SyntaxTree/tree/SyntaxTreeStreamReader.cs index 698680e37..5dbcb0341 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamReader.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamReader.cs @@ -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; + } + } diff --git a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs index 9a2d9bbb5..8fe609bc4 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs @@ -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); + } + } + } diff --git a/SyntaxTree/tree/Tree.cs b/SyntaxTree/tree/Tree.cs index 636b3d3eb..e75b9ec0f 100644 --- a/SyntaxTree/tree/Tree.cs +++ b/SyntaxTree/tree/Tree.cs @@ -16026,7 +16026,7 @@ namespace PascalABCCompiler.SyntaxTree ///expr:1:2 /// [Serializable] - public partial class format_expr : addressed_value + public partial class format_expr : expression { /// @@ -27675,6 +27675,216 @@ namespace PascalABCCompiler.SyntaxTree } + /// + /// + /// + [Serializable] + public partial class slice_expr : dereference + { + + /// + ///Конструктор без параметров. + /// + public slice_expr() + { + + } + + /// + ///Конструктор с параметрами. + /// + public slice_expr(addressed_value _v,expression _from,expression _to,expression _step) + { + this._v=_v; + this._from=_from; + this._to=_to; + this._step=_step; + } + + /// + ///Конструктор с параметрами. + /// + 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; + } + + /// + ///Конструктор с параметрами. + /// + 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; + } + + /// + ///Конструктор с параметрами. + /// + 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; + + /// + /// + /// + public addressed_value v + { + get + { + return _v; + } + set + { + _v=value; + } + } + + /// + /// + /// + public expression from + { + get + { + return _from; + } + set + { + _from=value; + } + } + + /// + /// + /// + public expression to + { + get + { + return _to; + } + set + { + _to=value; + } + } + + /// + /// + /// + public expression step + { + get + { + return _step; + } + set + { + _step=value; + } + } + + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 5; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 5; + } + } + /// + ///Индексатор для получения всех подузлов + /// + 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; + } + } + } + /// + ///Метод для обхода дерева посетителем + /// + ///Объект-посетитель. + ///Return value is void + public override void visit(IVisitor visitor) + { + visitor.visit(this); + } + + } + + } diff --git a/SyntaxTree/tree/Visitor.cs b/SyntaxTree/tree/Visitor.cs index ebdc987c5..c2d8a8848 100644 --- a/SyntaxTree/tree/Visitor.cs +++ b/SyntaxTree/tree/Visitor.cs @@ -1264,6 +1264,12 @@ namespace PascalABCCompiler.SyntaxTree ///Node to visit /// Return value is void void visit(dot_question_node _dot_question_node); + /// + ///Method to visit slice_expr. + /// + ///Node to visit + /// Return value is void + void visit(slice_expr _slice_expr); } diff --git a/SyntaxTree/tree/tree.nin b/SyntaxTree/tree/tree.nin index 8e6ec163f..532e27783 100644 Binary files a/SyntaxTree/tree/tree.nin and b/SyntaxTree/tree/tree.nin differ diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 17a76ed47..afed343d5 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -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 или реализует его + + 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 + { + 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; diff --git a/bin/Lib/PABCRtl.dll b/bin/Lib/PABCRtl.dll index 5d468a4a7..eb2efdcc5 100644 Binary files a/bin/Lib/PABCRtl.dll and b/bin/Lib/PABCRtl.dll differ diff --git a/bin/Lib/PABCSystem.axml b/bin/Lib/PABCSystem.axml index 5f706faea..a64ab3249 100644 --- a/bin/Lib/PABCSystem.axml +++ b/bin/Lib/PABCSystem.axml @@ -2497,6 +2497,15 @@ procedure Reset ( ) + + \PABCSystem.pas + function Slice<T>(Self: sequence of T; from,step: integer): sequence of T; extensionmethod; + + function Slice < T > ( Self : sequence of T ; from , step : integer ) : sequence of T extensionmethod + + + + \ No newline at end of file diff --git a/bin/Lib/PABCSystem.pas b/bin/Lib/PABCSystem.pas index 8fb07d1ce..4d9b0af4e 100644 --- a/bin/Lib/PABCSystem.pas +++ b/bin/Lib/PABCSystem.pas @@ -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(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(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; // ----------------------------------------------------- diff --git a/bin/Lng/Eng/SemanticErrors_ms.dat b/bin/Lng/Eng/SemanticErrors_ms.dat index ccce6463a..1708d80c3 100644 --- a/bin/Lng/Eng/SemanticErrors_ms.dat +++ b/bin/Lng/Eng/SemanticErrors_ms.dat @@ -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 \ No newline at end of file +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 diff --git a/bin/Lng/Rus/SemanticErrors_ms.dat b/bin/Lng/Rus/SemanticErrors_ms.dat index e27bd988e..478b78dcc 100644 --- a/bin/Lng/Rus/SemanticErrors_ms.dat +++ b/bin/Lng/Rus/SemanticErrors_ms.dat @@ -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=Îøèáî÷íàÿ êîíñòðóêöèÿ ïðè ïîñòðîåíèè òèïà êîðòåæà \ No newline at end of file +TUPLE_TYPE_ERROR=Îøèáî÷íàÿ êîíñòðóêöèÿ ïðè ïîñòðîåíèè òèïà êîðòåæà +INTEGER_VALUE_EXPECTED=Îæèäàëîñü çíà÷åíèå öåëîãî òèïà +BAD_SLICE_OBJECT=Ñðåçû äîïóñòèìû òîëüêî äëÿ ñòðîê, äèíàìè÷åñêèõ ìàññèâîâ, ñïèñêîâ è ïîñëåäîâàòåëüíîñòåé