Merge branch 'master' of https://github.com/pascalabcnet/pascalabcnet
Conflicts: bin/Lib/PABCRtl.dll
This commit is contained in:
commit
3e2be8178b
|
|
@ -2752,20 +2752,28 @@ namespace CodeFormatters
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (_modern_proc_type.el != null && _modern_proc_type.el.enumerators != null)
|
||||
if (_modern_proc_type.el == null && _modern_proc_type.res == null)
|
||||
{
|
||||
sb.Append("(");
|
||||
for (int i = 0; i < _modern_proc_type.el.enumerators.Count; i++)
|
||||
{
|
||||
visit_node(_modern_proc_type.el.enumerators[i]);
|
||||
}
|
||||
int beg_pos = GetPosition(_modern_proc_type.source_context.begin_position.line_num, _modern_proc_type.source_context.begin_position.column_num);
|
||||
int end_pos = GetPosition(_modern_proc_type.source_context.end_position.line_num, _modern_proc_type.source_context.end_position.column_num);
|
||||
sb.Append(Text.Substring(beg_pos, end_pos - beg_pos + 1));
|
||||
}
|
||||
else
|
||||
read_from_beg_pos = true;
|
||||
add_space_before = false;
|
||||
add_space_after = false;
|
||||
visit_node(_modern_proc_type.res);
|
||||
{
|
||||
if (_modern_proc_type.el != null && _modern_proc_type.el.enumerators != null)
|
||||
{
|
||||
sb.Append("(");
|
||||
for (int i = 0; i < _modern_proc_type.el.enumerators.Count; i++)
|
||||
{
|
||||
visit_node(_modern_proc_type.el.enumerators[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
read_from_beg_pos = true;
|
||||
add_space_before = false;
|
||||
add_space_after = false;
|
||||
visit_node(_modern_proc_type.res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ namespace CodeCompletion
|
|||
for (int i = 0; i < _named_type_reference.names.Count; i++)
|
||||
{
|
||||
if (i == _named_type_reference.names.Count - 1 && converted_template_type != null)
|
||||
suffix = "`" + _named_type_reference.names.Count;
|
||||
suffix = "`" + converted_template_type.params_list.params_list.Count;
|
||||
if (i > 0)
|
||||
returned_scope = returned_scope.FindNameOnlyInType(_named_type_reference.names[i].name+suffix);
|
||||
else
|
||||
|
|
@ -1081,10 +1081,27 @@ namespace CodeCompletion
|
|||
ps.declaringUnit = entry_scope;
|
||||
if (_procedure_header.template_args != null && !ps.IsGeneric())
|
||||
{
|
||||
Dictionary<string, TypeScope> where_types = new Dictionary<string, TypeScope>();
|
||||
if (_procedure_header.where_defs != null)
|
||||
{
|
||||
foreach (where_definition wd in _procedure_header.where_defs.defs)
|
||||
{
|
||||
for (int i = 0; i < wd.names.idents.Count; i++)
|
||||
{
|
||||
string name = wd.names.idents[i].name;
|
||||
wd.types.defs[i].visit(this);
|
||||
where_types[name] = returned_scope as TypeScope;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (ident s in _procedure_header.template_args.idents)
|
||||
{
|
||||
ps.AddTemplateParameter(s.name);
|
||||
TemplateParameterScope tps = new TemplateParameterScope(s.name, TypeTable.obj_type, ps);
|
||||
TypeScope where_ts = null;
|
||||
where_types.TryGetValue(s.name, out where_ts);
|
||||
if (where_ts == null)
|
||||
where_ts = TypeTable.obj_type;
|
||||
TemplateParameterScope tps = new TemplateParameterScope(s.name, where_ts, ps);
|
||||
tps.loc = get_location(s);
|
||||
ps.AddName(s.name, tps);
|
||||
}
|
||||
|
|
@ -1393,10 +1410,28 @@ namespace CodeCompletion
|
|||
SymScope tmp = cur_scope;
|
||||
if (_function_header.template_args != null && !ps.IsGeneric())
|
||||
{
|
||||
foreach (ident s in _function_header.template_args.idents)
|
||||
Dictionary<string, TypeScope> where_types = new Dictionary<string, TypeScope>();
|
||||
if (_function_header.where_defs != null)
|
||||
{
|
||||
foreach (where_definition wd in _function_header.where_defs.defs)
|
||||
{
|
||||
for (int i = 0; i < wd.names.idents.Count; i++)
|
||||
{
|
||||
string name = wd.names.idents[i].name;
|
||||
wd.types.defs[i].visit(this);
|
||||
where_types[name] = returned_scope as TypeScope;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (ident s in _function_header.template_args.idents)
|
||||
{
|
||||
ps.AddTemplateParameter(s.name);
|
||||
TemplateParameterScope tps = new TemplateParameterScope(s.name, TypeTable.obj_type, ps);
|
||||
TypeScope where_ts = null;
|
||||
where_types.TryGetValue(s.name, out where_ts);
|
||||
if (where_ts == null)
|
||||
where_ts = TypeTable.obj_type;
|
||||
TemplateParameterScope tps = new TemplateParameterScope(s.name, where_ts, ps);
|
||||
|
||||
tps.loc = get_location(s);
|
||||
ps.AddName(s.name, tps);
|
||||
}
|
||||
|
|
@ -4332,7 +4367,10 @@ namespace CodeCompletion
|
|||
if (_modern_proc_type.res != null)
|
||||
ttr.params_list.params_list.Add(_modern_proc_type.res);
|
||||
}
|
||||
visit(ttr);
|
||||
if (ttr.params_list.params_list.Count > 0)
|
||||
visit(ttr);
|
||||
else
|
||||
visit(ttr.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -305,6 +305,10 @@ namespace CodeCompletion
|
|||
if (extension_methods == null)
|
||||
extension_methods = new Dictionary<TypeScope, List<ProcScope>>();
|
||||
List<ProcScope> meth_list = null;
|
||||
if (ts is CompiledScope && (ts as CompiledScope).CompiledType.IsGenericType && !(ts as CompiledScope).CompiledType.IsGenericTypeDefinition)
|
||||
ts = TypeTable.get_compiled_type((ts as CompiledScope).CompiledType.GetGenericTypeDefinition());
|
||||
if (ts.original_type != null)
|
||||
ts = ts.original_type;
|
||||
if (!extension_methods.TryGetValue(ts, out meth_list))
|
||||
{
|
||||
meth_list = new List<ProcScope>();
|
||||
|
|
@ -347,7 +351,7 @@ namespace CodeCompletion
|
|||
{
|
||||
TypeScope tmp_ts2 = tmp_ts;
|
||||
if (tmp_ts is CompiledScope && (tmp_ts as CompiledScope).CompiledType.IsGenericType && !(tmp_ts as CompiledScope).CompiledType.IsGenericTypeDefinition)
|
||||
tmp_ts2 = TypeTable.get_compiled_type(new SymInfo("", SymbolKind.Class, ""), (tmp_ts as CompiledScope).CompiledType.GetGenericTypeDefinition());
|
||||
tmp_ts2 = TypeTable.get_compiled_type((tmp_ts as CompiledScope).CompiledType.GetGenericTypeDefinition());
|
||||
if (extension_methods.TryGetValue(tmp_ts2, out meths))
|
||||
{
|
||||
lst.AddRange(meths);
|
||||
|
|
@ -369,7 +373,7 @@ namespace CodeCompletion
|
|||
{
|
||||
TypeScope int_ts2 = int_ts;
|
||||
if (int_ts is CompiledScope && (int_ts as CompiledScope).CompiledType.IsGenericType && !(int_ts as CompiledScope).CompiledType.IsGenericTypeDefinition)
|
||||
int_ts2 = TypeTable.get_compiled_type(new SymInfo("", SymbolKind.Class, ""), (int_ts as CompiledScope).CompiledType.GetGenericTypeDefinition());
|
||||
int_ts2 = TypeTable.get_compiled_type((int_ts as CompiledScope).CompiledType.GetGenericTypeDefinition());
|
||||
if (extension_methods.TryGetValue(int_ts2, out meths))
|
||||
{
|
||||
lst.AddRange(meths);
|
||||
|
|
@ -4767,6 +4771,8 @@ namespace CodeCompletion
|
|||
public override TypeScope GetInstance(List<TypeScope> gen_args)
|
||||
{
|
||||
Type t = this.ctn;
|
||||
if (!ctn.IsGenericType)
|
||||
return this;
|
||||
if (!ctn.IsGenericTypeDefinition)
|
||||
t = PascalABCCompiler.NetHelper.NetHelper.FindType(this.ctn.Namespace + "." + this.ctn.Name);
|
||||
else if (this.instances != null && this.instances.Count > 0)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "1";
|
||||
public const string Build = "0";
|
||||
public const string Revision = "1247";
|
||||
public const string Revision = "1250";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%COREVERSION%=0
|
||||
%REVISION%=1247
|
||||
%MINOR%=1
|
||||
%REVISION%=1250
|
||||
%COREVERSION%=0
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -1634,7 +1634,22 @@ namespace PascalABCCompiler.Parsers
|
|||
Type[] tt = scope.CompiledMethod.GetGenericArguments();
|
||||
int gen_ind = 0;
|
||||
if (!scope.IsExtension)
|
||||
{
|
||||
sb.Append(GetShortTypeName(scope.CompiledMethod.DeclaringType));
|
||||
int ind = 0;
|
||||
foreach (Type gen_arg in scope.CompiledMethod.DeclaringType.GetGenericArguments())
|
||||
{
|
||||
if (gen_arg.IsGenericParameter)
|
||||
{
|
||||
if (generic_param_args == null)
|
||||
generic_param_args = new Dictionary<string, string>();
|
||||
if (scope.GenericArgs != null && scope.GenericArgs.Count > ind)
|
||||
generic_param_args.Add(gen_arg.Name, scope.GenericArgs[ind]);
|
||||
}
|
||||
ind++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
gen_ind = 1;
|
||||
|
|
@ -1648,6 +1663,8 @@ namespace PascalABCCompiler.Parsers
|
|||
{
|
||||
if (!class_generic_table.ContainsKey(class_generic_args[i].Name))
|
||||
class_generic_table.Add(class_generic_args[i].Name, j);
|
||||
if (scope.GenericArgs != null && scope.GenericArgs.Count > j)
|
||||
generic_param_args.Add(class_generic_args[i].Name, scope.GenericArgs[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.1.0.1247'
|
||||
!define VERSION '3.1.0.1250'
|
||||
|
|
|
|||
|
|
@ -1087,6 +1087,16 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
DefaultVisit(_yield_variable_definitions_with_unknown_type);
|
||||
}
|
||||
|
||||
public virtual void visit(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
DefaultVisit(_yield_unknown_foreach_type);
|
||||
}
|
||||
|
||||
public virtual void visit(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
DefaultVisit(_yield_unknown_foreach_type_ident);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1733,6 +1733,22 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void pre_do_visit(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
}
|
||||
|
||||
public virtual void post_do_visit(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
}
|
||||
|
||||
public override void visit(syntax_tree_node _syntax_tree_node)
|
||||
{
|
||||
DefaultVisit(_syntax_tree_node);
|
||||
|
|
@ -3588,6 +3604,22 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
visit(yield_variable_definitions_with_unknown_type.vars);
|
||||
post_do_visit(_yield_variable_definitions_with_unknown_type);
|
||||
}
|
||||
|
||||
public override void visit(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
DefaultVisit(_yield_unknown_foreach_type);
|
||||
pre_do_visit(_yield_unknown_foreach_type);
|
||||
visit(yield_unknown_foreach_type.unknown_foreach);
|
||||
post_do_visit(_yield_unknown_foreach_type);
|
||||
}
|
||||
|
||||
public override void visit(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
DefaultVisit(_yield_unknown_foreach_type_ident);
|
||||
pre_do_visit(_yield_unknown_foreach_type_ident);
|
||||
visit(yield_unknown_foreach_type_ident.unknown_foreach);
|
||||
post_do_visit(_yield_unknown_foreach_type_ident);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -452,6 +452,10 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
return new yield_var_def_statement_with_unknown_type();
|
||||
case 215:
|
||||
return new yield_variable_definitions_with_unknown_type();
|
||||
case 216:
|
||||
return new yield_unknown_foreach_type();
|
||||
case 217:
|
||||
return new yield_unknown_foreach_type_ident();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -3822,6 +3826,30 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
_yield_variable_definitions_with_unknown_type.vars = _read_node() as variable_definitions;
|
||||
}
|
||||
|
||||
|
||||
public void visit(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
read_yield_unknown_foreach_type(_yield_unknown_foreach_type);
|
||||
}
|
||||
|
||||
public void read_yield_unknown_foreach_type(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
read_type_definition(_yield_unknown_foreach_type);
|
||||
_yield_unknown_foreach_type.unknown_foreach = _read_node() as foreach_stmt;
|
||||
}
|
||||
|
||||
|
||||
public void visit(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
read_yield_unknown_foreach_type_ident(_yield_unknown_foreach_type_ident);
|
||||
}
|
||||
|
||||
public void read_yield_unknown_foreach_type_ident(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
read_ident(_yield_unknown_foreach_type_ident);
|
||||
_yield_unknown_foreach_type_ident.unknown_foreach = _read_node() as foreach_stmt;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6015,6 +6015,48 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
bw.Write((Int16)216);
|
||||
write_yield_unknown_foreach_type(_yield_unknown_foreach_type);
|
||||
}
|
||||
|
||||
public void write_yield_unknown_foreach_type(yield_unknown_foreach_type _yield_unknown_foreach_type)
|
||||
{
|
||||
write_type_definition(_yield_unknown_foreach_type);
|
||||
if (_yield_unknown_foreach_type.unknown_foreach == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_yield_unknown_foreach_type.unknown_foreach.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void visit(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
bw.Write((Int16)217);
|
||||
write_yield_unknown_foreach_type_ident(_yield_unknown_foreach_type_ident);
|
||||
}
|
||||
|
||||
public void write_yield_unknown_foreach_type_ident(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident)
|
||||
{
|
||||
write_ident(_yield_unknown_foreach_type_ident);
|
||||
if (_yield_unknown_foreach_type_ident.unknown_foreach == null)
|
||||
{
|
||||
bw.Write((byte)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
bw.Write((byte)1);
|
||||
_yield_unknown_foreach_type_ident.unknown_foreach.visit(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32039,6 +32039,271 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
}
|
||||
|
||||
|
||||
///<summary>
|
||||
///Узел для вычисления типа переменной используемой в теле foreach (с yield)
|
||||
///</summary>
|
||||
[Serializable]
|
||||
public partial class yield_unknown_foreach_type : type_definition
|
||||
{
|
||||
|
||||
///<summary>
|
||||
///Конструктор без параметров.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type(foreach_stmt _unknown_foreach)
|
||||
{
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type(foreach_stmt _unknown_foreach,SourceContext sc)
|
||||
{
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
source_context = sc;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type(type_definition_attr_list _attr_list,foreach_stmt _unknown_foreach)
|
||||
{
|
||||
this._attr_list=_attr_list;
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type(type_definition_attr_list _attr_list,foreach_stmt _unknown_foreach,SourceContext sc)
|
||||
{
|
||||
this._attr_list=_attr_list;
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
source_context = sc;
|
||||
}
|
||||
|
||||
protected foreach_stmt _unknown_foreach;
|
||||
|
||||
///<summary>
|
||||
///
|
||||
///</summary>
|
||||
public foreach_stmt unknown_foreach
|
||||
{
|
||||
get
|
||||
{
|
||||
return _unknown_foreach;
|
||||
}
|
||||
set
|
||||
{
|
||||
_unknown_foreach=value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///<summary>
|
||||
///Свойство для получения количества всех подузлов без элементов поля типа List
|
||||
///</summary>
|
||||
public override Int32 subnodes_without_list_elements_count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
///<summary>
|
||||
///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List
|
||||
///</summary>
|
||||
public override Int32 subnodes_count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
///<summary>
|
||||
///Индексатор для получения всех подузлов
|
||||
///</summary>
|
||||
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 attr_list;
|
||||
case 1:
|
||||
return unknown_foreach;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
|
||||
throw new IndexOutOfRangeException();
|
||||
switch(ind)
|
||||
{
|
||||
case 0:
|
||||
attr_list = (type_definition_attr_list)value;
|
||||
break;
|
||||
case 1:
|
||||
unknown_foreach = (foreach_stmt)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
///<summary>
|
||||
///Метод для обхода дерева посетителем
|
||||
///</summary>
|
||||
///<param name="visitor">Объект-посетитель.</param>
|
||||
///<returns>Return value is void</returns>
|
||||
public override void visit(IVisitor visitor)
|
||||
{
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
///<summary>
|
||||
///Узел для приведения типа enumerator.Current к типу переменной цикла foreach
|
||||
///</summary>
|
||||
[Serializable]
|
||||
public partial class yield_unknown_foreach_type_ident : ident
|
||||
{
|
||||
|
||||
///<summary>
|
||||
///Конструктор без параметров.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type_ident()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type_ident(foreach_stmt _unknown_foreach)
|
||||
{
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type_ident(foreach_stmt _unknown_foreach,SourceContext sc)
|
||||
{
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
source_context = sc;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type_ident(string _name,foreach_stmt _unknown_foreach)
|
||||
{
|
||||
this._name=_name;
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
}
|
||||
|
||||
///<summary>
|
||||
///Конструктор с параметрами.
|
||||
///</summary>
|
||||
public yield_unknown_foreach_type_ident(string _name,foreach_stmt _unknown_foreach,SourceContext sc)
|
||||
{
|
||||
this._name=_name;
|
||||
this._unknown_foreach=_unknown_foreach;
|
||||
source_context = sc;
|
||||
}
|
||||
|
||||
protected foreach_stmt _unknown_foreach;
|
||||
|
||||
///<summary>
|
||||
///
|
||||
///</summary>
|
||||
public foreach_stmt unknown_foreach
|
||||
{
|
||||
get
|
||||
{
|
||||
return _unknown_foreach;
|
||||
}
|
||||
set
|
||||
{
|
||||
_unknown_foreach=value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///<summary>
|
||||
///Свойство для получения количества всех подузлов без элементов поля типа List
|
||||
///</summary>
|
||||
public override Int32 subnodes_without_list_elements_count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
///<summary>
|
||||
///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List
|
||||
///</summary>
|
||||
public override Int32 subnodes_count
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
///<summary>
|
||||
///Индексатор для получения всех подузлов
|
||||
///</summary>
|
||||
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 unknown_foreach;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
set
|
||||
{
|
||||
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
|
||||
throw new IndexOutOfRangeException();
|
||||
switch(ind)
|
||||
{
|
||||
case 0:
|
||||
unknown_foreach = (foreach_stmt)value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
///<summary>
|
||||
///Метод для обхода дерева посетителем
|
||||
///</summary>
|
||||
///<param name="visitor">Объект-посетитель.</param>
|
||||
///<returns>Return value is void</returns>
|
||||
public override void visit(IVisitor visitor)
|
||||
{
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1300,6 +1300,18 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
///<param name="_yield_variable_definitions_with_unknown_type">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(yield_variable_definitions_with_unknown_type _yield_variable_definitions_with_unknown_type);
|
||||
///<summary>
|
||||
///Method to visit yield_unknown_foreach_type.
|
||||
///</summary>
|
||||
///<param name="_yield_unknown_foreach_type">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(yield_unknown_foreach_type _yield_unknown_foreach_type);
|
||||
///<summary>
|
||||
///Method to visit yield_unknown_foreach_type_ident.
|
||||
///</summary>
|
||||
///<param name="_yield_unknown_foreach_type_ident">Node to visit</param>
|
||||
///<returns> Return value is void </returns>
|
||||
void visit(yield_unknown_foreach_type_ident _yield_unknown_foreach_type_ident);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -11,8 +11,6 @@ end;
|
|||
|
||||
|
||||
begin
|
||||
//var a := Arr(1,2,3);
|
||||
//System.Linq.Enumerable.Select(a,x->x); - жаль - пока не работает. Закомментил чтобы тесты не падали
|
||||
var a := Arr(1,2,3);
|
||||
var seq := System.Linq.Enumerable.Select(a,x->x*2);
|
||||
//a.Reverse.Print;
|
||||
|
|
|
|||
7
TestSuite/extensionmethods17.pas
Normal file
7
TestSuite/extensionmethods17.pas
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
begin
|
||||
var s := '1234';
|
||||
var fnc: char->boolean := char.IsDigit;
|
||||
assert(s.All(fnc) = true);
|
||||
assert(s.All&<char>(char.IsDigit) = true);
|
||||
assert(s.All&<char>(char.IsControl) = false);
|
||||
end.
|
||||
10
TestSuite/intellisense_tests/extensionmethods1.pas
Normal file
10
TestSuite/intellisense_tests/extensionmethods1.pas
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
//ä
|
||||
begin
|
||||
var l := Seq(2,1,4);
|
||||
l.OfType&<integer>().ForEach{@(расширение) procedure ForEach<T>(Self: sequence of T; action: T->());@}(x->Print(x));
|
||||
var l1 := new List<integer>;
|
||||
var seq1{@var seq1: sequence of integer;@} := l1.Where{@(расширение) function IEnumerable<>.Where<>(predicate: integer->boolean): sequence of integer;@}(i->true);
|
||||
var l2 := l1.ConvertAll&{@function List<>.ConvertAll<TOutput>(converter: Converter<integer,TOutput>): List<TOutput>;@}<real>();
|
||||
var seq2{@var seq2: sequence of integer;@} := l1.Skip{@(расширение) function IEnumerable<>.Skip<>(count: integer): sequence of integer;@}(3);
|
||||
l1.OrderBy(i->i).Skip{@(расширение) function IEnumerable<>.Skip<>(count: integer): sequence of integer;@}(3);
|
||||
end.
|
||||
15
TestSuite/intellisense_tests/where1.pas
Normal file
15
TestSuite/intellisense_tests/where1.pas
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//ä
|
||||
function Test<T>(a, b: T): integer; where T:System.IComparable<T>;
|
||||
begin
|
||||
var x: T;
|
||||
x.CompareTo{@function IComparable<>.CompareTo(other: T): integer; virtual;@}(a);
|
||||
end;
|
||||
|
||||
procedure Test2<T>(a, b: T); where T:System.IComparable<real>;
|
||||
begin
|
||||
var x: T;
|
||||
x.CompareTo{@function IComparable<>.CompareTo(other: real): integer; virtual;@}(a);
|
||||
end;
|
||||
|
||||
begin
|
||||
end.
|
||||
17
TestSuite/with1.pas
Normal file
17
TestSuite/with1.pas
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
type TClass = class
|
||||
a: integer;
|
||||
end;
|
||||
|
||||
begin
|
||||
var obj := new TClass;
|
||||
with obj do
|
||||
begin
|
||||
a := 2;
|
||||
assert(a = 2);
|
||||
end;
|
||||
var lst := Lst(1,2,3);
|
||||
with lst do
|
||||
begin
|
||||
assert(Count = 3);
|
||||
end;
|
||||
end.
|
||||
|
|
@ -4667,6 +4667,15 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
// end frninja
|
||||
|
||||
// frninja 29/05/16 - для приведения типов в lowered foreach
|
||||
if (_method_call.dereferencing_value is yield_unknown_foreach_type_ident)
|
||||
{
|
||||
var nodeToVisit = new method_call(GetForeachVariableTypeName((_method_call.dereferencing_value as yield_unknown_foreach_type_ident).unknown_foreach), _method_call.parameters);
|
||||
visit(nodeToVisit);
|
||||
return;
|
||||
}
|
||||
// end frninja
|
||||
|
||||
//lroman
|
||||
if (_method_call.dereferencing_value is closure_substituting_node)
|
||||
{
|
||||
|
|
@ -8538,22 +8547,25 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
case general_node_type.function_node:
|
||||
{
|
||||
//TODO: Передается пустой список выражений.
|
||||
/*
|
||||
function_node fn=convertion_data_and_alghoritms.select_function(new expressions_list(),
|
||||
si_right,get_location(id_right));
|
||||
return create_static_method_call(fn,get_location(id_right),tn,false);
|
||||
*/
|
||||
//if (!(si_right.sym_info is common_in_function_function_node))
|
||||
if (dn is compiled_function_node)
|
||||
{
|
||||
if ((dn as compiled_function_node).ConnectedToType == tn)
|
||||
AddError(new UndefinedNameReference(id_right.name, get_location(id_right)));
|
||||
{
|
||||
if (si_right.Next != null)
|
||||
return create_static_expression(tn, id_right, si_right.Next);
|
||||
else
|
||||
AddError(new UndefinedNameReference(id_right.name, get_location(id_right)));
|
||||
}
|
||||
}
|
||||
else if (dn is common_namespace_function_node)
|
||||
{
|
||||
if ((dn as common_namespace_function_node).ConnectedToType == tn)
|
||||
AddError(new UndefinedNameReference(id_right.name, get_location(id_right)));
|
||||
{
|
||||
if (si_right.Next != null)
|
||||
return create_static_expression(tn, id_right, si_right.Next);
|
||||
else
|
||||
AddError(new UndefinedNameReference(id_right.name, get_location(id_right)));
|
||||
}
|
||||
}
|
||||
if (dn.semantic_node_type == semantic_node_type.indefinite_definition_node)
|
||||
{
|
||||
|
|
@ -18999,7 +19011,11 @@ namespace PascalABCCompiler.TreeConverter
|
|||
public override void visit(SyntaxTree.yield_var_def_statement_with_unknown_type _vars)
|
||||
{
|
||||
if ((object)_vars.vars.vars_type != null)
|
||||
{
|
||||
// Visit stored vars
|
||||
_vars.vars.visit(this);
|
||||
return;
|
||||
}
|
||||
var t = convert_strong(_vars.vars.inital_value);
|
||||
_vars.map_helper.vars_type_map[_vars.vars] = new SyntaxTree.semantic_type_node(t.type);
|
||||
|
||||
|
|
@ -19013,7 +19029,9 @@ namespace PascalABCCompiler.TreeConverter
|
|||
foreach (var vd in _vars.vars.list)
|
||||
{
|
||||
if ((object)vd.vars_type != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var t = convert_strong(vd.inital_value);
|
||||
_vars.map_helper.vars_type_map[vd] = new SyntaxTree.semantic_type_node(t.type);
|
||||
}
|
||||
|
|
@ -19022,6 +19040,53 @@ namespace PascalABCCompiler.TreeConverter
|
|||
_vars.vars.visit(this);
|
||||
}
|
||||
|
||||
// frninja 29/05/16 - выявляем тип перемнной в foreach
|
||||
public override void visit(SyntaxTree.yield_unknown_foreach_type _unk)
|
||||
{
|
||||
var _foreach_stmt = _unk.unknown_foreach;
|
||||
expression_node in_what = convert_strong(_foreach_stmt.in_what);
|
||||
type_node elem_type = null;
|
||||
if (!FindIEnumerableElementType(_foreach_stmt, in_what.type, ref elem_type))
|
||||
{
|
||||
AddError(in_what.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", in_what.type.name);
|
||||
}
|
||||
// Visit type
|
||||
var t = new SyntaxTree.semantic_type_node(elem_type);
|
||||
t.visit(this);
|
||||
}
|
||||
|
||||
private ident GetForeachVariableTypeName(foreach_stmt _foreach_stmt)
|
||||
{
|
||||
type_node tn;
|
||||
|
||||
/*if (_foreach_stmt.type_name == null)
|
||||
{
|
||||
// Внешнее имя, ищем тип
|
||||
var cv = convert_strong(_foreach_stmt.identifier);
|
||||
tn = cv.type;
|
||||
}
|
||||
else*/
|
||||
{
|
||||
expression_node in_what = convert_strong(_foreach_stmt.in_what);
|
||||
type_node elem_type = null;
|
||||
if (!FindIEnumerableElementType(_foreach_stmt, in_what.type, ref elem_type))
|
||||
{
|
||||
AddError(in_what.location, "CAN_NOT_EXECUTE_FOREACH_BY_EXPR_OF_TYPE_{0}", in_what.type.name);
|
||||
}
|
||||
tn = elem_type;
|
||||
}
|
||||
|
||||
return new SyntaxTree.ident(tn.name);
|
||||
}
|
||||
|
||||
// frninja 29/05/16 - получаем имя типа переменной в foreach
|
||||
public override void visit(SyntaxTree.yield_unknown_foreach_type_ident _unk)
|
||||
{
|
||||
var t = this.GetForeachVariableTypeName(_unk.unknown_foreach);
|
||||
// Visit type
|
||||
t.visit(this);
|
||||
}
|
||||
|
||||
// end frninja
|
||||
|
||||
/*public SyntaxTree.question_colon_expression ConvertToQCE(dot_question_node dqn)
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ namespace VisualPascalABCPlugins
|
|||
void Button2Click(object sender, EventArgs e)
|
||||
{
|
||||
CodeCompletion.CodeCompletionTester.Test();
|
||||
CodeCompletion.CodeCompletionTester.TestIntellisense(Path.Combine(@"c:\Work\Miks\_PABCNETGitHub\TestSuite", "intellisense_tests"));
|
||||
MessageBox.Show("Done");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@
|
|||
<Compile Include="YieldVisitors\RenameSameBlockLocalVarsVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceCapturedVariablesVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceFormalParametersRefsVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceForVariableVisitor.cs" />
|
||||
<Compile Include="YieldVisitors\ReplaceVariableNameVisitor.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Compiler\Compiler.csproj">
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace SyntaxVisitors
|
|||
{
|
||||
var sts = st as statement;
|
||||
|
||||
if (sts != null && !(sts is statement_list) && !(UpperNode() is statement_list))
|
||||
if (sts != null && !(sts is statement_list) && !(sts is case_variant) && !(UpperNode() is statement_list))
|
||||
{
|
||||
// Одиночный оператор
|
||||
var stl = new statement_list(sts, st.source_context);
|
||||
|
|
@ -25,8 +25,8 @@ namespace SyntaxVisitors
|
|||
|
||||
|
||||
var lst = st as labeled_statement;
|
||||
|
||||
if (lst != null && !(lst.to_statement is statement_list))
|
||||
|
||||
if (lst != null && !(lst.to_statement is statement_list) && !(lst.to_statement is case_variant))
|
||||
{
|
||||
// Одиночный оператор
|
||||
var stl = new statement_list(sts, st.source_context);
|
||||
|
|
|
|||
|
|
@ -114,6 +114,15 @@ namespace SyntaxVisitors
|
|||
base.visit(fn);
|
||||
}
|
||||
|
||||
public override void visit(foreach_stmt frch)
|
||||
{
|
||||
if (frch.type_name != null)
|
||||
{
|
||||
CheckVariableAlreadyDefined(frch.identifier);
|
||||
}
|
||||
base.visit(frch);
|
||||
}
|
||||
|
||||
private bool IsVariableAlreadyDefined(string name)
|
||||
{
|
||||
if (UpperBlockNames.Contains(name))
|
||||
|
|
|
|||
|
|
@ -34,12 +34,7 @@ namespace SyntaxVisitors
|
|||
}
|
||||
|
||||
private int _varnum = 0;
|
||||
|
||||
private string newVarName()
|
||||
{
|
||||
_varnum++;
|
||||
return "<>varLV" + _varnum.ToString();
|
||||
}
|
||||
private int _enumeratorNum = 0;
|
||||
|
||||
private VarNames NewVarNames(ident name)
|
||||
{
|
||||
|
|
@ -51,6 +46,12 @@ namespace SyntaxVisitors
|
|||
};
|
||||
}
|
||||
|
||||
private ident NewEnumeratorName()
|
||||
{
|
||||
++_enumeratorNum;
|
||||
return "$enumerator$" + _enumeratorNum;
|
||||
}
|
||||
|
||||
public static void Accept(procedure_definition pd)
|
||||
{
|
||||
New.ProcessNode(pd);
|
||||
|
|
@ -67,13 +68,149 @@ namespace SyntaxVisitors
|
|||
|
||||
|
||||
|
||||
// frninja 21/05/16
|
||||
/*public override void visit(foreach_stmt frch)
|
||||
public override void visit(yield_unknown_foreach_type _unk)
|
||||
{
|
||||
ProcessNode(frch.stmt);
|
||||
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
}*/
|
||||
public override void visit(yield_unknown_foreach_type_ident _unk)
|
||||
{
|
||||
// DO NOTHING
|
||||
}
|
||||
|
||||
// frninja 21/05/16
|
||||
public override void visit(foreach_stmt frch)
|
||||
{
|
||||
var enumeratorIdent = this.NewEnumeratorName();
|
||||
|
||||
// Переменная цикла
|
||||
var currentIdent = frch.identifier;
|
||||
type_definition currentIdentType = null;
|
||||
|
||||
// Новое тело
|
||||
var stl = new statement_list();
|
||||
|
||||
// С типом
|
||||
if (frch.type_name == null)
|
||||
{
|
||||
// Внешнее имя, создавать ниче не надо
|
||||
}
|
||||
else
|
||||
{
|
||||
// var имеет место быть
|
||||
if (frch.type_name is no_type_foreach)
|
||||
{
|
||||
// автовывод
|
||||
currentIdentType = new yield_unknown_foreach_type(frch);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentIdentType = frch.type_name;
|
||||
}
|
||||
|
||||
// Получаем служебное имя с $ и заменяем его в теле цикла
|
||||
currentIdent = this.NewVarNames(frch.identifier).VarName;
|
||||
var replacerVis = new ReplaceVariableNameVisitor(frch.identifier, currentIdent);
|
||||
frch.visit(replacerVis);
|
||||
|
||||
|
||||
// Создаем переменную цикла и добавляем в stl
|
||||
stl.Add(new var_statement(currentIdent, currentIdentType));
|
||||
|
||||
}
|
||||
|
||||
// Добавляем $current$ = $enumerator$.Current
|
||||
//stl.Add(new assign(currentIdent, new dot_node(enumeratorIdent, "Current")));
|
||||
stl.Add(new assign(currentIdent, new method_call(new yield_unknown_foreach_type_ident(frch), new expression_list(new dot_node(enumeratorIdent, "Current")))));
|
||||
|
||||
|
||||
// Добавляем тело цикла в stl
|
||||
ProcessNode(frch.stmt);
|
||||
stl.Add(frch.stmt);
|
||||
|
||||
var whileNode = new while_node(new method_call(new dot_node(enumeratorIdent, "MoveNext"), new expression_list()),
|
||||
stl,
|
||||
WhileCycleType.While);
|
||||
|
||||
ReplaceStatement(frch,
|
||||
SeqStatements(new var_statement(enumeratorIdent,
|
||||
new named_type_reference("System.Collections.IEnumerator"),
|
||||
// НЕБЕЗОПАСНО!
|
||||
new method_call(new dot_node(frch.in_what as addressed_value, new ident("GetEnumerator")), new expression_list())),
|
||||
whileNode));
|
||||
|
||||
}
|
||||
|
||||
private expression CreateConditionFromCaseVariant(expression param, expression_list list)
|
||||
{
|
||||
var res = list.expressions.Aggregate(new bool_const(false) as expression, (acc, expr) =>
|
||||
{
|
||||
bin_expr currentExpr = null;
|
||||
diapason_expr diap = expr as diapason_expr;
|
||||
if (diap != null)
|
||||
{
|
||||
currentExpr = new bin_expr(new bin_expr(param, diap.left, Operators.GreaterEqual),
|
||||
new bin_expr(param, diap.right, Operators.LessEqual),
|
||||
Operators.LogicalAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentExpr = new bin_expr(param, expr, Operators.Equal);
|
||||
}
|
||||
|
||||
return new bin_expr(acc, currentExpr, Operators.LogicalOR);
|
||||
});
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// frninja 30/05/16
|
||||
public override void visit(case_node csn)
|
||||
{
|
||||
var b = HasStatementVisitor<yield_node>.Has(csn);
|
||||
if (!b)
|
||||
return;
|
||||
|
||||
/*
|
||||
*
|
||||
* case i of
|
||||
* cv1: bla1;
|
||||
* cv2: bla2;
|
||||
* ..
|
||||
* cvN: blaN;
|
||||
* else: bla_else;
|
||||
*
|
||||
* --->
|
||||
*
|
||||
* if i satisfy cv1
|
||||
* then bla1
|
||||
* else if i satisfy cv2
|
||||
* then bla2
|
||||
* ..
|
||||
* else if i satisfy cvN
|
||||
* then blaN
|
||||
* else bla_else
|
||||
*
|
||||
*/
|
||||
|
||||
if_node currentIfNode = null;
|
||||
statement currentIfElseClause = (csn.else_statement != null) ? csn.else_statement :new statement_list(new empty_statement()); ;
|
||||
|
||||
for (int i = csn.conditions.variants.Count - 1; i >= 0; --i)
|
||||
{
|
||||
case_variant cv = csn.conditions.variants[i];
|
||||
|
||||
ProcessNode(cv.exec_if_true);
|
||||
|
||||
var ifCondition = this.CreateConditionFromCaseVariant(csn.param, cv.conditions);
|
||||
currentIfNode = new if_node(ifCondition, new statement_list(cv.exec_if_true), new statement_list(currentIfElseClause));
|
||||
currentIfElseClause = currentIfNode;
|
||||
}
|
||||
|
||||
if_node finalIfNode = currentIfNode;
|
||||
|
||||
ReplaceStatement(csn, finalIfNode);
|
||||
}
|
||||
|
||||
public override void visit(if_node ifn)
|
||||
{
|
||||
|
|
@ -179,7 +316,7 @@ namespace SyntaxVisitors
|
|||
var newLoopVar = fn.create_loop_variable ? new ident(newNames.VarName) : fn.loop_variable;
|
||||
|
||||
// Нужно заменить fn.loop_variable -> newLoopVar в теле цикла
|
||||
var replacerVis = new ReplaceForVariableVisitor(fn.loop_variable, newLoopVar);
|
||||
var replacerVis = new ReplaceVariableNameVisitor(fn.loop_variable, newLoopVar);
|
||||
fn.visit(replacerVis);
|
||||
|
||||
fn.loop_variable = newLoopVar;
|
||||
|
|
|
|||
|
|
@ -445,6 +445,72 @@ namespace SyntaxVisitors
|
|||
}
|
||||
}
|
||||
|
||||
// frninja 31/05/16
|
||||
/// <summary>
|
||||
/// Вставляет метод-хелпер
|
||||
/// </summary>
|
||||
/// <param name="pd">Метод-итератор</param>
|
||||
/// <param name="helper">Метод-хелпер</param>
|
||||
private void InsertHelperMethod(procedure_definition pd, procedure_definition helper)
|
||||
{
|
||||
if (IsClassMethod(pd))
|
||||
{
|
||||
var cd = UpperTo<class_definition>();
|
||||
if (cd != null)
|
||||
{
|
||||
// Метод класса описан в классе
|
||||
var classMembers = UpperTo<class_members>();
|
||||
classMembers.Add(helper);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Метод класса описан вне класса
|
||||
|
||||
var decls = UpperTo<declarations>();
|
||||
var classMembers = decls.list
|
||||
.Select(decl => decl as type_declarations)
|
||||
.Where(tdecls => tdecls != null)
|
||||
.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)
|
||||
.SelectMany(_cd => _cd.body.class_def_blocks);
|
||||
|
||||
|
||||
// Вставляем предописание метода-хелпера
|
||||
var helperPredefHeader = ObjectCopier.Clone(helper.proc_header);
|
||||
helperPredefHeader.name.class_name = null;
|
||||
classMembers.First().members.Insert(0, helperPredefHeader);
|
||||
|
||||
// Вставляем тело метода-хелпера
|
||||
UpperTo<declarations>().InsertBefore(pd, helper);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UpperTo<declarations>().InsertBefore(pd, helper);
|
||||
}
|
||||
}
|
||||
|
||||
// frninja 31/05/16
|
||||
/// <summary>
|
||||
/// Вставляет клон метода-итератора для того, чтобы проверить ошибки существующим бэкендом (пересечение диапазонов case, повторные объявления переменных)
|
||||
/// </summary>
|
||||
/// <param name="pd"></param>
|
||||
private void CreateErrorCheckerHelper(procedure_definition pd)
|
||||
{
|
||||
// Клонируем исходный метод для проверок ошибок бэкендом
|
||||
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.is_yield_helper = true;
|
||||
|
||||
InsertHelperMethod(pd, pdCloned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Обработка локальных переменных метода и их типов для корректного захвата
|
||||
/// </summary>
|
||||
|
|
@ -473,43 +539,7 @@ namespace SyntaxVisitors
|
|||
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.is_yield_helper = true;
|
||||
|
||||
if (IsClassMethod(pd))
|
||||
{
|
||||
var cd = UpperTo<class_definition>();
|
||||
if (cd != null)
|
||||
{
|
||||
// Метод класса описан в классе
|
||||
var classMembers = UpperTo<class_members>();
|
||||
classMembers.Add(pdCloned);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Метод класса описан вне класса
|
||||
|
||||
var decls = UpperTo<declarations>();
|
||||
var classMembers = decls.list
|
||||
.Select(decl => decl as type_declarations)
|
||||
.Where(tdecls => tdecls != null)
|
||||
.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)
|
||||
.SelectMany(_cd => _cd.body.class_def_blocks);
|
||||
|
||||
|
||||
// Вставляем предописание метода-хелпера
|
||||
var helperPredefHeader = ObjectCopier.Clone(pdCloned.proc_header);
|
||||
helperPredefHeader.name.class_name = null;
|
||||
classMembers.First().members.Insert(0, helperPredefHeader);
|
||||
|
||||
// Вставляем тело метода-хелпера
|
||||
UpperTo<declarations>().InsertBefore(pd, pdCloned);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UpperTo<declarations>().InsertBefore(pd, pdCloned);
|
||||
}
|
||||
InsertHelperMethod(pd, pdCloned);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -537,6 +567,8 @@ namespace SyntaxVisitors
|
|||
return localsClonesMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Вставляем описание классов-хелперов для yield перед методом-итератором в зависимости от его описания
|
||||
/// </summary>
|
||||
|
|
@ -582,6 +614,7 @@ namespace SyntaxVisitors
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Захватываем имена в методе
|
||||
/// </summary>
|
||||
|
|
@ -691,6 +724,8 @@ namespace SyntaxVisitors
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override void visit(procedure_definition pd)
|
||||
{
|
||||
if (!pd.has_yield)
|
||||
|
|
@ -712,10 +747,14 @@ namespace SyntaxVisitors
|
|||
//if (!hasYields) // т.е. мы разобрали функцию и уже выходим. Это значит, что пока yield будет обрабатываться только в функциях. Так это и надо.
|
||||
// return;
|
||||
|
||||
// frninja 31/05/16 - добавляем метод-хелпер, возьмет на себя проверку разных ошибок уже существующим бэкендом
|
||||
CreateErrorCheckerHelper(pd);
|
||||
|
||||
// frninja 24/05/16 - оборачиваем одиночные операторы в begin..end
|
||||
AddBeginEndsVisitor addBeginEndsVis = new AddBeginEndsVisitor();
|
||||
pd.visit(addBeginEndsVis);
|
||||
|
||||
/*
|
||||
// Проверяем проблемы имен для for
|
||||
CheckVariablesRedefenitionVisitor checkVarRedefVisitor = new CheckVariablesRedefenitionVisitor(
|
||||
new HashSet<string>(
|
||||
|
|
@ -725,6 +764,7 @@ namespace SyntaxVisitors
|
|||
:
|
||||
Enumerable.Empty<string>()));
|
||||
pd.visit(checkVarRedefVisitor);
|
||||
*/
|
||||
|
||||
// Переименовываем одинаковые имена в мини-ПИ
|
||||
RenameSameBlockLocalVarsVisitor renameLocalsVisitor = new RenameSameBlockLocalVarsVisitor();
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ using PascalABCCompiler.SyntaxTree;
|
|||
|
||||
namespace SyntaxVisitors
|
||||
{
|
||||
public class ReplaceForVariableVisitor : BaseChangeVisitor
|
||||
public class ReplaceVariableNameVisitor : BaseChangeVisitor
|
||||
{
|
||||
private ident _oldName;
|
||||
private ident _newName;
|
||||
|
||||
public ReplaceForVariableVisitor(ident oldName, ident newName)
|
||||
public ReplaceVariableNameVisitor(ident oldName, ident newName)
|
||||
{
|
||||
_oldName = oldName;
|
||||
_newName = newName;
|
||||
Binary file not shown.
Loading…
Reference in a new issue