diff --git a/CodeCompletion/ExpressionVisitor.cs b/CodeCompletion/ExpressionVisitor.cs index 0bca9dd86..d9a0848e4 100644 --- a/CodeCompletion/ExpressionVisitor.cs +++ b/CodeCompletion/ExpressionVisitor.cs @@ -88,9 +88,13 @@ namespace CodeCompletion } else if (returned_scope != null && returned_scope is ElementScope && (returned_scope as ElementScope).sc is ProcScope) { - if (by_dot) - if (((returned_scope as ElementScope).sc as ProcScope).return_type != null) - returned_scope = new ElementScope(((returned_scope as ElementScope).sc as ProcScope).return_type); + ProcScope ps = (returned_scope as ElementScope).sc as ProcScope; + TypeScope return_type = ps.return_type; + if (ps.is_constructor) + return_type = ps.declaringType; + if (by_dot) + if (return_type != null) + returned_scope = new ElementScope(return_type); else returned_scope = null; } @@ -101,14 +105,18 @@ namespace CodeCompletion returned_scope = new ElementScope(invoke_meth.return_type); } else if (returned_scope != null && returned_scope is ProcScope) - if ((returned_scope as ProcScope).return_type == null) + { + ProcScope ps = returned_scope as ProcScope; + TypeScope return_type = ps.return_type; + if (ps.is_constructor) + return_type = ps.declaringType; + if (return_type == null) { if (by_dot) returned_scope = null; } - else if (by_dot) - returned_scope = new ElementScope((returned_scope as ProcScope).return_type); - - //else ret_scope = (ret_scope as ElementScope).sc as ProcScope; + else if (by_dot) + returned_scope = new ElementScope(return_type); + } return returned_scope; } @@ -723,9 +731,13 @@ namespace CodeCompletion } else if (returned_scope != null && returned_scope is ProcScope) { - if ((returned_scope as ProcScope).return_type == null) + ProcScope ps = returned_scope as ProcScope; + if (ps.return_type == null) { - returned_scope = null; + if (ps.is_constructor) + returned_scope = new ElementScope(ps.declaringType); + else + returned_scope = null; } else returned_scope = new ElementScope((returned_scope as ProcScope).return_type); @@ -924,9 +936,12 @@ namespace CodeCompletion ps = returned_scope as ProcScope; if (by_dot) { - if (ps.return_type != null) - returned_scope = new ElementScope(ps.return_type); - else returned_scope = null; + if (ps.return_type != null) + returned_scope = new ElementScope(ps.return_type); + else if (ps.is_constructor) + returned_scope = new ElementScope(ps.declaringType); + else + returned_scope = null; } else returned_scope = new ElementScope(ps); diff --git a/SyntaxTree/tree/HierarchyVisitor.cs b/SyntaxTree/tree/HierarchyVisitor.cs index c2e05ed94..d0149bc5b 100644 --- a/SyntaxTree/tree/HierarchyVisitor.cs +++ b/SyntaxTree/tree/HierarchyVisitor.cs @@ -3576,8 +3576,6 @@ namespace PascalABCCompiler.SyntaxTree { DefaultVisit(_yield_unknown_ident); pre_do_visit(_yield_unknown_ident); - visit(yield_unknown_ident.UnknownID); - visit(yield_unknown_ident.ClassName); post_do_visit(_yield_unknown_ident); } diff --git a/SyntaxTree/tree/SyntaxTreeStreamReader.cs b/SyntaxTree/tree/SyntaxTreeStreamReader.cs index 4696fabaa..fe1e6cd6b 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamReader.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamReader.cs @@ -3786,8 +3786,6 @@ namespace PascalABCCompiler.SyntaxTree public void read_yield_unknown_ident(yield_unknown_ident _yield_unknown_ident) { read_ident(_yield_unknown_ident); - _yield_unknown_ident.UnknownID = _read_node() as ident; - _yield_unknown_ident.ClassName = _read_node() as ident; } diff --git a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs index 4d1d0bd9f..13481c117 100644 --- a/SyntaxTree/tree/SyntaxTreeStreamWriter.cs +++ b/SyntaxTree/tree/SyntaxTreeStreamWriter.cs @@ -5932,24 +5932,6 @@ namespace PascalABCCompiler.SyntaxTree public void write_yield_unknown_ident(yield_unknown_ident _yield_unknown_ident) { write_ident(_yield_unknown_ident); - if (_yield_unknown_ident.UnknownID == null) - { - bw.Write((byte)0); - } - else - { - bw.Write((byte)1); - _yield_unknown_ident.UnknownID.visit(this); - } - if (_yield_unknown_ident.ClassName == null) - { - bw.Write((byte)0); - } - else - { - bw.Write((byte)1); - _yield_unknown_ident.ClassName.visit(this); - } } diff --git a/SyntaxTree/tree/Tree.cs b/SyntaxTree/tree/Tree.cs index c5d089b15..22b9fc904 100644 --- a/SyntaxTree/tree/Tree.cs +++ b/SyntaxTree/tree/Tree.cs @@ -31542,80 +31542,24 @@ namespace PascalABCCompiler.SyntaxTree } - /// - ///Конструктор с параметрами. - /// - public yield_unknown_ident(ident _UnknownID,ident _ClassName) - { - this._UnknownID=_UnknownID; - this._ClassName=_ClassName; - } /// ///Конструктор с параметрами. /// - public yield_unknown_ident(ident _UnknownID,ident _ClassName,SourceContext sc) - { - this._UnknownID=_UnknownID; - this._ClassName=_ClassName; - source_context = sc; - } - - /// - ///Конструктор с параметрами. - /// - public yield_unknown_ident(string _name,ident _UnknownID,ident _ClassName) + public yield_unknown_ident(string _name) { this._name=_name; - this._UnknownID=_UnknownID; - this._ClassName=_ClassName; } /// ///Конструктор с параметрами. /// - public yield_unknown_ident(string _name,ident _UnknownID,ident _ClassName,SourceContext sc) + public yield_unknown_ident(string _name,SourceContext sc) { this._name=_name; - this._UnknownID=_UnknownID; - this._ClassName=_ClassName; source_context = sc; } - protected ident _UnknownID; - protected ident _ClassName; - - /// - /// - /// - public ident UnknownID - { - get - { - return _UnknownID; - } - set - { - _UnknownID=value; - } - } - - /// - /// - /// - public ident ClassName - { - get - { - return _ClassName; - } - set - { - _ClassName=value; - } - } - - /// ///Свойство для получения количества всех подузлов без элементов поля типа List /// @@ -31623,7 +31567,7 @@ namespace PascalABCCompiler.SyntaxTree { get { - return 2; + return 0; } } /// @@ -31633,7 +31577,7 @@ namespace PascalABCCompiler.SyntaxTree { get { - return 2; + return 0; } } /// @@ -31645,28 +31589,12 @@ namespace PascalABCCompiler.SyntaxTree { if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) throw new IndexOutOfRangeException(); - switch(ind) - { - case 0: - return UnknownID; - case 1: - return ClassName; - } return null; } set { if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1) throw new IndexOutOfRangeException(); - switch(ind) - { - case 0: - UnknownID = (ident)value; - break; - case 1: - ClassName = (ident)value; - break; - } } } /// diff --git a/SyntaxTree/tree/TreeHelper.cs b/SyntaxTree/tree/TreeHelper.cs index 7fe902723..6954a9b82 100644 --- a/SyntaxTree/tree/TreeHelper.cs +++ b/SyntaxTree/tree/TreeHelper.cs @@ -1447,6 +1447,45 @@ namespace PascalABCCompiler.SyntaxTree } } + public partial class yield_unknown_ident : ident + { + protected ident _UnknownID; + protected ident _ClassName; + + public ident UnknownID + { + get { return _UnknownID; } + set { _UnknownID = value; } + } + + public ident ClassName + { + get { return _ClassName; } + set { _ClassName = value; } + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_ident(ident _UnknownID, ident _ClassName) + { + this._name = _UnknownID.name; + this._UnknownID = _UnknownID; + this._ClassName = _ClassName; + } + + /// + ///Конструктор с параметрами. + /// + public yield_unknown_ident(ident _UnknownID, ident _ClassName, SourceContext sc) + { + this._name = _UnknownID.name; + this._UnknownID = _UnknownID; + this._ClassName = _ClassName; + source_context = sc; + } + } + // end frninja diff --git a/SyntaxTree/tree/tree.nin b/SyntaxTree/tree/tree.nin index 8db24b7b9..fe3305118 100644 Binary files a/SyntaxTree/tree/tree.nin and b/SyntaxTree/tree/tree.nin differ diff --git a/TestSuite/intellisense_tests/create1.pas b/TestSuite/intellisense_tests/create1.pas new file mode 100644 index 000000000..c646fd7e2 --- /dev/null +++ b/TestSuite/intellisense_tests/create1.pas @@ -0,0 +1,9 @@ +type A = class + f: sequence of integer; +end; + +begin + A.Create{@constructor A();@}.f{@var A.f: sequence of integer;@}.Println; + A.Create().f{@var A.f: sequence of integer;@}.Println; + StringBuilder.Create{@constructor StringBuilder();@}.ToString{@function StringBuilder.ToString(): string; virtual;@}; +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/compilation_context.cs b/TreeConverter/TreeConversion/compilation_context.cs index 64f980170..d08b704c6 100644 --- a/TreeConverter/TreeConversion/compilation_context.cs +++ b/TreeConverter/TreeConversion/compilation_context.cs @@ -914,12 +914,6 @@ namespace PascalABCCompiler.TreeConverter public void leave_type_method() { - // frninja 03/06/16 - убираем мусорные методы-хелперы yield - if (_ctn != null && (top_function is common_method_node) && (top_function as common_method_node).is_yield_helper) - { - _ctn.methods.remove(top_function as common_method_node); - } - // end frninja if (_explicit_interface_type != null) { function_node fn = top_function; diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index bf41bea25..381844f15 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -11507,6 +11507,12 @@ namespace PascalABCCompiler.TreeConverter { if (_procedure_definition.proc_header.name.class_name != null) { + // frninja 03/06/16 - убираем мусорные методы-хелперы yield + if (context._ctn != null && (context.top_function is common_method_node) && (context.top_function as common_method_node).is_yield_helper) + { + context._ctn.methods.remove(context.top_function as common_method_node); + } + // end frninja context.leave_type_method(); } context.is_order_independed_method_description = false; diff --git a/Yield/SyntaxVisitors/YieldVisitors/LoweringVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/LoweringVisitor.cs index e042d046b..6f7aa4804 100644 --- a/Yield/SyntaxVisitors/YieldVisitors/LoweringVisitor.cs +++ b/Yield/SyntaxVisitors/YieldVisitors/LoweringVisitor.cs @@ -324,9 +324,13 @@ namespace SyntaxVisitors var endtemp = new ident(newNames.VarEndName); //new ident(newVarName()); //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value); - var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value); + //var ass1 = new var_statement(fn.loop_variable, fn.type_name, fn.initial_value); //var ass2 = new var_statement(endtemp, fn.type_name, fn.finish_value); + // frninja 05/06/16 - фиксим для !fn.create_variable + var ass1 = fn.create_loop_variable + ? new var_statement(fn.loop_variable, fn.type_name, fn.initial_value) as statement + : new assign(fn.loop_variable, fn.initial_value) as statement; var if0 = new if_node((fn.cycle_type == for_cycle_type.to) ? diff --git a/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs b/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs index b82e5d1e1..7721f2775 100644 --- a/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs +++ b/Yield/SyntaxVisitors/YieldVisitors/MarkMethodHasYieldVisitor.cs @@ -19,6 +19,8 @@ namespace SyntaxVisitors { this.CurrentMethod = pd; + HasYields = false; + base.visit(pd); pd.has_yield = HasYields; diff --git a/Yield/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs b/Yield/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs index 538b7edb2..567fb9a02 100644 --- a/Yield/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs +++ b/Yield/SyntaxVisitors/YieldVisitors/ProcessYieldsCapturedVars.cs @@ -254,9 +254,16 @@ namespace SyntaxVisitors interfaces1.Add(IEnumerableT).Add(IEnumeratorT); // frninja 24/04/16 - поддержка шаблонных классов - var td1 = new type_declaration(className, this.CreateHelperClassDefinition(className, pd, interfaces1, cm1)); + + // frninja 05/06/16 - фикс. Поддержка where секции + var helperClassDefinition = this.CreateHelperClassDefinition(className, pd, interfaces1, cm1); + helperClassDefinition.where_section = this.GetMethodWhereSection(pd); + + var td1 = new type_declaration(className, helperClassDefinition); //SyntaxTreeBuilder.BuildClassDefinition(interfaces1, cm1)); + + var cct = new type_declarations(/*td*/); cct.Add(td1); @@ -356,6 +363,67 @@ namespace SyntaxVisitors return null; } + private class_definition GetMethodClassDefinition(procedure_definition pd) + { + if (!IsClassMethod(pd)) + { + return null; + } + + var cd = UpperTo(); + if (cd != null) + { + // Метод класса описан в классе + return cd; + } + else + { + // Метод класса описан вне класса + + return UpperTo().list + .OfType() + .SelectMany(tdecls => tdecls.types_decl) + .Where(td => td.type_name.name == GetClassName(pd).name) + .Select(td => td.type_def as class_definition) + .Where(_cd => _cd != null) + .DefaultIfEmpty() + .First(); + } + } + + private where_definition_list GetMethodWhereSection(procedure_definition pd) + { + if (!IsClassMethod(pd)) + { + if (pd.proc_header.where_defs != null) + { + return ObjectCopier.Clone(pd.proc_header.where_defs); + } + else + { + var pdPredefs = UpperTo().defs + .OfType() + .Where(lpd => lpd.proc_body == null + && lpd.proc_header.name.meth_name.name == pd.proc_header.name.meth_name.name + && lpd.proc_header.proc_attributes.proc_attributes.FindIndex(attr => attr.attribute_type == proc_attribute.attr_forward) != -1); + if (pdPredefs.Count() > 0) + { + return ObjectCopier.Clone(pdPredefs.First().proc_header.where_defs); + } + } + } + else + { + class_definition cd = GetMethodClassDefinition(pd); + if (cd != null) + { + return ObjectCopier.Clone(cd.where_section); + } + } + + return null; + } + /// /// Определяет описан ли метод-итератор в некотором классе /// @@ -503,11 +571,14 @@ namespace SyntaxVisitors { // Клонируем исходный метод для проверок ошибок бэкендом var pdCloned = ObjectCopier.Clone(pd); + pdCloned.has_yield = false; // Добавляем в класс метод с обертками для локальных переменных - pdCloned.proc_header.name.meth_name = new ident(YieldConsts.YieldHelperMethodPrefix + "_error_checkerr>" + pd.proc_header.name.meth_name.name); // = new method_name("" + pd.proc_header.className.meth_name.className); + pdCloned.proc_header.name.meth_name = new ident(YieldConsts.YieldHelperMethodPrefix + "_error_checkerr>" + pd.proc_header.name.meth_name.name, + // frninja 05/06/16 - фиксим source_context + pd.proc_header.name.meth_name.source_context); // = new method_name("" + pd.proc_header.className.meth_name.className); //pdCloned.is_yield_helper = true; InsertHelperMethod(pd, pdCloned); @@ -524,6 +595,7 @@ namespace SyntaxVisitors // Клонируем исходный метод для вставки оберток-хелперов для локальных переменных и дальнейшей обработки на семантике var pdCloned = ObjectCopier.Clone(pd); + pdCloned.has_yield = false; // Заменяем локальные переменные с неизвестным типом на обертки-хелперы (откладываем до семантики) @@ -538,7 +610,9 @@ namespace SyntaxVisitors localsClonesCollection = localsTypeDetectorHelperVisitor.LocalDeletedDefs.ToArray(); // Добавляем в класс метод с обертками для локальных переменных - pdCloned.proc_header.name.meth_name = new ident(YieldConsts.YieldHelperMethodPrefix+ "_locals_type_detector>" + pd.proc_header.name.meth_name.name); // = new method_name("" + pd.proc_header.className.meth_name.className); + pdCloned.proc_header.name.meth_name = new ident(YieldConsts.YieldHelperMethodPrefix+ "_locals_type_detector>" + pd.proc_header.name.meth_name.name, + // frninja 05/06/16 - фиксим source_context + pd.proc_header.name.meth_name.source_context); // = new method_name("" + pd.proc_header.className.meth_name.className); //pdCloned.is_yield_helper = true; InsertHelperMethod(pd, pdCloned); @@ -726,7 +800,42 @@ namespace SyntaxVisitors return false; } - + /// + /// Вставляет предописание метода-итератора для рекурсивных вызовов, если метод описан вне класса + /// + private bool InsertGlobalIteratorMethodPredefinition(procedure_definition pd) + { + if (IsClassMethod(pd)) + { + return false; + } + + var pdPredefs = UpperTo().defs + .OfType() + .Where(lpd => lpd.proc_body == null + && lpd.proc_header.name.meth_name.name == pd.proc_header.name.meth_name.name + && lpd.proc_header.proc_attributes.proc_attributes.FindIndex(attr => attr.attribute_type == proc_attribute.attr_forward) != -1); + + + bool isPredefined = pdPredefs.Count() > 0; + + if (!isPredefined) + { + + var fh = ObjectCopier.Clone(pd.proc_header as function_header); + fh.proc_attributes.Add(new procedure_attribute(proc_attribute.attr_forward)); + + procedure_definition predef = new procedure_definition() { proc_header = fh }; + // frninja 05/06/16 - для шаблонов с where + predef.proc_header.where_defs = ObjectCopier.Clone(pd.proc_header.where_defs); + + UpperTo().AddFirst(predef); + + return true; + } + + return false; + } public override void visit(procedure_definition pd) { @@ -751,6 +860,9 @@ namespace SyntaxVisitors // frninja 31/05/16 - добавляем метод-хелпер, возьмет на себя проверку разных ошибок уже существующим бэкендом CreateErrorCheckerHelper(pd); + + // frninja 05/06/16 - вставляем предописание если метод-итератор описан не в классе (обычная функция) чтоб работали рекурсивные вызовы + bool methodPredefCreated = InsertGlobalIteratorMethodPredefinition(pd); // frninja 24/05/16 - оборачиваем одиночные операторы в begin..end AddBeginEndsVisitor addBeginEndsVis = new AddBeginEndsVisitor(); @@ -821,6 +933,12 @@ namespace SyntaxVisitors // frninja 20/05/16 - фикс для повторного обхода pd.has_yield = false; + // frninja 05/06/16 - убираем where-секцию у описания метода. Они уже скопированы куда надо + if (methodPredefCreated) + { + pd.proc_header.where_defs = null; + } + //mids = null; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть }