diff --git a/SyntaxTree/tree/AbstractVisitor.cs b/SyntaxTree/tree/AbstractVisitor.cs index 9847684ec..c68e43bc4 100644 --- a/SyntaxTree/tree/AbstractVisitor.cs +++ b/SyntaxTree/tree/AbstractVisitor.cs @@ -1098,9 +1098,14 @@ namespace PascalABCCompiler.SyntaxTree DefaultVisit(_slice_expr_question); } - public virtual void visit(semantic_check_sugared_statement _semantic_check_sugared_statement) + public virtual void visit(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) { - DefaultVisit(_semantic_check_sugared_statement); + DefaultVisit(_semantic_check_sugared_statement_node); + } + + public virtual void visit(sugared_expression _sugared_expression) + { + DefaultVisit(_sugared_expression); } } diff --git a/SyntaxTree/tree/HierarchyVisitor.cs b/SyntaxTree/tree/HierarchyVisitor.cs index 6ec7c9281..560d8b405 100644 --- a/SyntaxTree/tree/HierarchyVisitor.cs +++ b/SyntaxTree/tree/HierarchyVisitor.cs @@ -1749,11 +1749,19 @@ namespace PascalABCCompiler.SyntaxTree { } - public virtual void pre_do_visit(semantic_check_sugared_statement _semantic_check_sugared_statement) + public virtual void pre_do_visit(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) { } - public virtual void post_do_visit(semantic_check_sugared_statement _semantic_check_sugared_statement) + public virtual void post_do_visit(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) + { + } + + public virtual void pre_do_visit(sugared_expression _sugared_expression) + { + } + + public virtual void post_do_visit(sugared_expression _sugared_expression) { } @@ -3623,11 +3631,19 @@ namespace PascalABCCompiler.SyntaxTree post_do_visit(_slice_expr_question); } - public override void visit(semantic_check_sugared_statement _semantic_check_sugared_statement) + public override void visit(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) { - DefaultVisit(_semantic_check_sugared_statement); - pre_do_visit(_semantic_check_sugared_statement); - post_do_visit(_semantic_check_sugared_statement); + DefaultVisit(_semantic_check_sugared_statement_node); + pre_do_visit(_semantic_check_sugared_statement_node); + post_do_visit(_semantic_check_sugared_statement_node); + } + + public override void visit(sugared_expression _sugared_expression) + { + DefaultVisit(_sugared_expression); + pre_do_visit(_sugared_expression); + visit(sugared_expression.new_expr); + post_do_visit(_sugared_expression); } } diff --git a/SyntaxTree/tree/SyntaxTreeStreamReader.cs b/SyntaxTree/tree/SyntaxTreeStreamReader.cs index 4da4b0b0b..845d310f1 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamReader.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamReader.cs @@ -457,7 +457,9 @@ namespace PascalABCCompiler.SyntaxTree case 217: return new slice_expr_question(); case 218: - return new semantic_check_sugared_statement(); + return new semantic_check_sugared_statement_node(); + case 219: + return new sugared_expression(); } return null; } @@ -3847,15 +3849,28 @@ namespace PascalABCCompiler.SyntaxTree } - public void visit(semantic_check_sugared_statement _semantic_check_sugared_statement) + public void visit(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) { - read_semantic_check_sugared_statement(_semantic_check_sugared_statement); + read_semantic_check_sugared_statement_node(_semantic_check_sugared_statement_node); } - public void read_semantic_check_sugared_statement(semantic_check_sugared_statement _semantic_check_sugared_statement) + public void read_semantic_check_sugared_statement_node(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) { - read_statement(_semantic_check_sugared_statement); - _semantic_check_sugared_statement.stat = (object)br.ReadByte(); + read_statement(_semantic_check_sugared_statement_node); + _semantic_check_sugared_statement_node.stat = (object)br.ReadByte(); + } + + + public void visit(sugared_expression _sugared_expression) + { + read_sugared_expression(_sugared_expression); + } + + public void read_sugared_expression(sugared_expression _sugared_expression) + { + read_expression(_sugared_expression); + _sugared_expression.sugared_expr = (object)br.ReadByte(); + _sugared_expression.new_expr = _read_node() as expression; } } diff --git a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs index 82bde377e..060c599c2 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs @@ -6004,16 +6004,38 @@ namespace PascalABCCompiler.SyntaxTree } - public void visit(semantic_check_sugared_statement _semantic_check_sugared_statement) + public void visit(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) { bw.Write((Int16)218); - write_semantic_check_sugared_statement(_semantic_check_sugared_statement); + write_semantic_check_sugared_statement_node(_semantic_check_sugared_statement_node); } - public void write_semantic_check_sugared_statement(semantic_check_sugared_statement _semantic_check_sugared_statement) + public void write_semantic_check_sugared_statement_node(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node) { - write_statement(_semantic_check_sugared_statement); - bw.Write((byte)_semantic_check_sugared_statement.stat); + write_statement(_semantic_check_sugared_statement_node); + bw.Write((byte)_semantic_check_sugared_statement_node.stat); + } + + + public void visit(sugared_expression _sugared_expression) + { + bw.Write((Int16)219); + write_sugared_expression(_sugared_expression); + } + + public void write_sugared_expression(sugared_expression _sugared_expression) + { + write_expression(_sugared_expression); + bw.Write((byte)_sugared_expression.sugared_expr); + if (_sugared_expression.new_expr == null) + { + bw.Write((byte)0); + } + else + { + bw.Write((byte)1); + _sugared_expression.new_expr.visit(this); + } } } diff --git a/SyntaxTree/tree/Tree.cs b/SyntaxTree/tree/Tree.cs index 76ad7534f..04fc1173d 100644 --- a/SyntaxTree/tree/Tree.cs +++ b/SyntaxTree/tree/Tree.cs @@ -38529,13 +38529,13 @@ namespace PascalABCCompiler.SyntaxTree ///узел, не генерирующий кода, но осуществляющий семантические проверки сахарных узлов. stat - это на самом деле statement. stat сделано типа object - чтобы оно автоматически не обходилось /// [Serializable] - public partial class semantic_check_sugared_statement : statement + public partial class semantic_check_sugared_statement_node : statement { /// ///Конструктор без параметров. /// - public semantic_check_sugared_statement() + public semantic_check_sugared_statement_node() { } @@ -38543,7 +38543,7 @@ namespace PascalABCCompiler.SyntaxTree /// ///Конструктор с параметрами. /// - public semantic_check_sugared_statement(object _stat) + public semantic_check_sugared_statement_node(object _stat) { this._stat=_stat; } @@ -38551,7 +38551,7 @@ namespace PascalABCCompiler.SyntaxTree /// ///Конструктор с параметрами. /// - public semantic_check_sugared_statement(object _stat,SourceContext sc) + public semantic_check_sugared_statement_node(object _stat,SourceContext sc) { this._stat=_stat; source_context = sc; @@ -38577,7 +38577,7 @@ namespace PascalABCCompiler.SyntaxTree /// Создает копию узла public override syntax_tree_node Clone() { - semantic_check_sugared_statement copy = new semantic_check_sugared_statement(); + semantic_check_sugared_statement_node copy = new semantic_check_sugared_statement_node(); copy.Parent = this.Parent; if (source_context != null) copy.source_context = new SourceContext(source_context); @@ -38591,9 +38591,9 @@ namespace PascalABCCompiler.SyntaxTree } /// Получает копию данного узла корректного типа - public new semantic_check_sugared_statement TypedClone() + public new semantic_check_sugared_statement_node TypedClone() { - return Clone() as semantic_check_sugared_statement; + return Clone() as semantic_check_sugared_statement_node; } /// @@ -38646,6 +38646,161 @@ namespace PascalABCCompiler.SyntaxTree } + /// + /// + /// + [Serializable] + public partial class sugared_expression : expression + { + + /// + ///Конструктор без параметров. + /// + public sugared_expression() + { + + } + + /// + ///Конструктор с параметрами. + /// + public sugared_expression(object _sugared_expr,expression _new_expr) + { + this._sugared_expr=_sugared_expr; + this._new_expr=_new_expr; + } + + /// + ///Конструктор с параметрами. + /// + public sugared_expression(object _sugared_expr,expression _new_expr,SourceContext sc) + { + this._sugared_expr=_sugared_expr; + this._new_expr=_new_expr; + source_context = sc; + } + protected object _sugared_expr; + protected expression _new_expr; + + /// + /// + /// + public object sugared_expr + { + get + { + return _sugared_expr; + } + set + { + _sugared_expr=value; + } + } + + /// + /// + /// + public expression new_expr + { + get + { + return _new_expr; + } + set + { + _new_expr=value; + } + } + + + /// Создает копию узла + public override syntax_tree_node Clone() + { + sugared_expression copy = new sugared_expression(); + copy.Parent = this.Parent; + if (source_context != null) + copy.source_context = new SourceContext(source_context); + if (attributes != null) + { + copy.attributes = (attribute_list)attributes.Clone(); + copy.attributes.Parent = copy; + } + copy.sugared_expr = sugared_expr; + if (new_expr != null) + { + copy.new_expr = (expression)new_expr.Clone(); + copy.new_expr.Parent = copy; + } + return copy; + } + + /// Получает копию данного узла корректного типа + public new sugared_expression TypedClone() + { + return Clone() as sugared_expression; + } + + /// + ///Свойство для получения количества всех подузлов без элементов поля типа List + /// + public override Int32 subnodes_without_list_elements_count + { + get + { + return 1; + } + } + /// + ///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List + /// + public override Int32 subnodes_count + { + get + { + return 1; + } + } + /// + ///Индексатор для получения всех подузлов + /// + 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 new_expr; + } + return null; + } + set + { + if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) + throw new IndexOutOfRangeException(); + switch(ind) + { + case 0: + new_expr = (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 e284f2f33..d41e89f83 100644 --- a/SyntaxTree/tree/Visitor.cs +++ b/SyntaxTree/tree/Visitor.cs @@ -1313,11 +1313,17 @@ namespace PascalABCCompiler.SyntaxTree /// Return value is void void visit(slice_expr_question _slice_expr_question); /// - ///Method to visit semantic_check_sugared_statement. + ///Method to visit semantic_check_sugared_statement_node. /// - ///Node to visit + ///Node to visit /// Return value is void - void visit(semantic_check_sugared_statement _semantic_check_sugared_statement); + void visit(semantic_check_sugared_statement_node _semantic_check_sugared_statement_node); + /// + ///Method to visit sugared_expression. + /// + ///Node to visit + /// Return value is void + void visit(sugared_expression _sugared_expression); } diff --git a/SyntaxTree/tree/tree.nin b/SyntaxTree/tree/tree.nin index 38caa0a9c..7c94f8d48 100644 Binary files a/SyntaxTree/tree/tree.nin and b/SyntaxTree/tree/tree.nin differ diff --git a/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs b/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs index ce94d6f36..d103dd369 100644 --- a/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs +++ b/SyntaxVisitors/SugarVisitors/AssignTuplesDesugarVisitor.cs @@ -25,7 +25,7 @@ namespace SyntaxVisitors.SugarVisitors public override void visit(assign_tuple asstup) { var sl = new statement_list(); - sl.Add(new semantic_check_sugared_statement(asstup)); // Это нужно для проверок на этапе преобразования в семантику + sl.Add(new semantic_check_sugared_statement_node(asstup)); // Это нужно для проверок на этапе преобразования в семантику var tname = "#temp_var" + UniqueNumStr(); var tt = new var_statement(new ident(tname), asstup.expr); @@ -48,7 +48,7 @@ namespace SyntaxVisitors.SugarVisitors public override void visit(assign_var_tuple assvartup) { var sl = new List(); - sl.Add(new semantic_check_sugared_statement(assvartup)); // Это нужно для проверок на этапе преобразования в семантику + sl.Add(new semantic_check_sugared_statement_node(assvartup)); // Это нужно для проверок на этапе преобразования в семантику var tname = "#temp_var" + UniqueNumStr(); var tt = new var_statement(new ident(tname), assvartup.expr); // тут для assvartup.expr внутри повторно вызывается convert_strong, это плохо, но если там лямбда, то иначе - с semantic_addr_value - не работает!!! diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index fe9e91961..d597c3e89 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -19415,19 +19415,25 @@ namespace PascalABCCompiler.TreeConverter visit(pc); } - public override void visit(SyntaxTree.semantic_check_sugared_statement st) + public override void visit(SyntaxTree.semantic_check_sugared_statement_node st) { - if (st.stat is SyntaxTree.assign_var_tuple) + if (st.stat is SyntaxTree.assign_tuple) { - check_sugared(st.stat as SyntaxTree.assign_var_tuple); + check_sugared(st.stat as SyntaxTree.assign_tuple); } - else + else { - + AddError(get_location(st), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}"); } ret.reset(); // обязательно очистить - этот узел в семантику ничего не должен приносить! } + public override void visit(SyntaxTree.sugared_expression ex) + { + //semantic_check_sugared_expression(ex.sugared_expr); + visit(ex.new_expr); + } + /*public SyntaxTree.question_colon_expression ConvertToQCE(dot_question_node dqn) { // Неверно работает. Пока не используется. Доделать diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor_semcheck_helper.cs b/TreeConverter/TreeConversion/syntax_tree_visitor_semcheck_helper.cs new file mode 100644 index 000000000..10d39bcb3 --- /dev/null +++ b/TreeConverter/TreeConversion/syntax_tree_visitor_semcheck_helper.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using PascalABCCompiler.SyntaxTree; +using PascalABCCompiler.TreeRealization; + +namespace PascalABCCompiler.TreeConverter +{ + public partial class syntax_tree_visitor + { + void semcheck_slice_expr_helper(SyntaxTree.slice_expr sl) + { + var semvar = convert_strong(sl.v); + if (semvar is typed_expression) + semvar = convert_typed_expression_to_function_call(semvar as typed_expression); + + var t = ConvertSemanticTypeNodeToNETType(semvar.type); + + var IsSlicedType = 0; // проверим, является ли semvar.type динамическим массивом, списком List или строкой + // semvar.type должен быть array of T, List или string + if (t == null) + IsSlicedType = 0; // можно ничего не присваивать :) + else if (t.IsArray) + IsSlicedType = 1; + else if (t == typeof(System.String)) + IsSlicedType = 2; + else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(System.Collections.Generic.List<>)) + IsSlicedType = 3; + + if (IsSlicedType == 0) + AddError(get_location(sl.v), "BAD_SLICE_OBJECT"); + + var semfrom = convert_strong(sl.from); + var b = convertion_data_and_alghoritms.can_convert_type(semfrom, SystemLibrary.SystemLibrary.integer_type); + if (!b) + AddError(get_location(sl.from), "INTEGER_VALUE_EXPECTED"); + + var semto = convert_strong(sl.to); + b = convertion_data_and_alghoritms.can_convert_type(semto, SystemLibrary.SystemLibrary.integer_type); + if (!b) + AddError(get_location(sl.to), "INTEGER_VALUE_EXPECTED"); + + if (sl.step != null) + { + var semstep = convert_strong(sl.step); + b = convertion_data_and_alghoritms.can_convert_type(semstep, SystemLibrary.SystemLibrary.integer_type); + if (!b) + AddError(get_location(sl.step), "INTEGER_VALUE_EXPECTED"); + } + } + public void semcheck(SyntaxTree.slice_expr sl) + { + semcheck_slice_expr_helper(sl); + } + public void semcheck(SyntaxTree.slice_expr_question sl) + { + semcheck_slice_expr_helper(sl); + } + } +} diff --git a/bin/Lng/Eng/SemanticErrors_ms.dat b/bin/Lng/Eng/SemanticErrors_ms.dat index 0dd37f785..3681c51a8 100644 --- a/bin/Lng/Eng/SemanticErrors_ms.dat +++ b/bin/Lng/Eng/SemanticErrors_ms.dat @@ -9,3 +9,5 @@ BAD_SLICE_OBJECT=Slices are allowed for strings, dynamic arrays and lists only ONLY_IN_SHORT_FUNC_DEFS_RETURN_TYPE_CANBE_OMITTED=Only in short function definitions you can omit the return type ONE_TKIDENTIFIER=Type here must be identifier SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR=Sugared node {0} must not be visited in syntax_tree_visitor +MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}=Missed semantic check for sugared node {0} + diff --git a/bin/Lng/Rus/SemanticErrors_ms.dat b/bin/Lng/Rus/SemanticErrors_ms.dat index cd368059f..b6ab547d3 100644 --- a/bin/Lng/Rus/SemanticErrors_ms.dat +++ b/bin/Lng/Rus/SemanticErrors_ms.dat @@ -9,3 +9,4 @@ BAD_SLICE_OBJECT=Срезы допустимы только для строк, ONLY_IN_SHORT_FUNC_DEFS_RETURN_TYPE_CANBE_OMITTED=Только в коротких определениях функций можно не указывать тип возвращаемого значения ONE_TKIDENTIFIER=В качестве типа ожидался идентификатор SUGARED_NODE_{0}_IN_SYNTAX_TREE_VISITOR=Сахарный узел {0} не должен обходиться в syntax_tree_visitor. Обратитесь к разработчикам PascalABC.NET +MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}=Отсутствует семантическая проверка для сахарного узла {0}