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; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть
}