This commit is contained in:
miks1965 2016-06-06 11:40:56 +03:00
commit 85a81c8cb2
13 changed files with 215 additions and 122 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -31542,80 +31542,24 @@ namespace PascalABCCompiler.SyntaxTree
}
///<summary>
///Конструктор с параметрами.
///</summary>
public yield_unknown_ident(ident _UnknownID,ident _ClassName)
{
this._UnknownID=_UnknownID;
this._ClassName=_ClassName;
}
///<summary>
///Конструктор с параметрами.
///</summary>
public yield_unknown_ident(ident _UnknownID,ident _ClassName,SourceContext sc)
{
this._UnknownID=_UnknownID;
this._ClassName=_ClassName;
source_context = sc;
}
///<summary>
///Конструктор с параметрами.
///</summary>
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;
}
///<summary>
///Конструктор с параметрами.
///</summary>
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;
///<summary>
///
///</summary>
public ident UnknownID
{
get
{
return _UnknownID;
}
set
{
_UnknownID=value;
}
}
///<summary>
///
///</summary>
public ident ClassName
{
get
{
return _ClassName;
}
set
{
_ClassName=value;
}
}
///<summary>
///Свойство для получения количества всех подузлов без элементов поля типа List
///</summary>
@ -31623,7 +31567,7 @@ namespace PascalABCCompiler.SyntaxTree
{
get
{
return 2;
return 0;
}
}
///<summary>
@ -31633,7 +31577,7 @@ namespace PascalABCCompiler.SyntaxTree
{
get
{
return 2;
return 0;
}
}
///<summary>
@ -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;
}
}
}
///<summary>

View file

@ -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; }
}
///<summary>
///Конструктор с параметрами.
///</summary>
public yield_unknown_ident(ident _UnknownID, ident _ClassName)
{
this._name = _UnknownID.name;
this._UnknownID = _UnknownID;
this._ClassName = _ClassName;
}
///<summary>
///Конструктор с параметрами.
///</summary>
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

Binary file not shown.

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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) ?

View file

@ -19,6 +19,8 @@ namespace SyntaxVisitors
{
this.CurrentMethod = pd;
HasYields = false;
base.visit(pd);
pd.has_yield = HasYields;

View file

@ -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<class_definition>();
if (cd != null)
{
// Метод класса описан в классе
return cd;
}
else
{
// Метод класса описан вне класса
return UpperTo<declarations>().list
.OfType<type_declarations>()
.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<declarations>().defs
.OfType<procedure_definition>()
.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;
}
/// <summary>
/// Определяет описан ли метод-итератор в некотором классе
/// </summary>
@ -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("<yield_helper_locals_type_detector>" + 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("<yield_helper_locals_type_detector>" + 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("<yield_helper_locals_type_detector>" + 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("<yield_helper_locals_type_detector>" + pd.proc_header.className.meth_name.className);
//pdCloned.is_yield_helper = true;
InsertHelperMethod(pd, pdCloned);
@ -726,7 +800,42 @@ namespace SyntaxVisitors
return false;
}
/// <summary>
/// Вставляет предописание метода-итератора для рекурсивных вызовов, если метод описан вне класса
/// </summary>
private bool InsertGlobalIteratorMethodPredefinition(procedure_definition pd)
{
if (IsClassMethod(pd))
{
return false;
}
var pdPredefs = UpperTo<declarations>().defs
.OfType<procedure_definition>()
.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<declarations>().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; // вдруг мы выйдем из процедуры, не зайдем в другую, а там - оператор! Такого конечно не может быть
}