Conflicts:
	bin/Lib/PABCRtl.dll
This commit is contained in:
miks1965 2016-06-01 06:16:38 +03:00
commit 3e2be8178b
28 changed files with 845 additions and 88 deletions

View file

@ -2752,7 +2752,14 @@ namespace CodeFormatters
}
else
{
if (_modern_proc_type.el == null && _modern_proc_type.res == null)
{
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
{
if (_modern_proc_type.el != null && _modern_proc_type.el.enumerators != null)
{
sb.Append("(");
@ -2768,6 +2775,7 @@ namespace CodeFormatters
visit_node(_modern_proc_type.res);
}
}
}
public override void visit(tuple_node_for_formatter _tuple_node_for_formatter)
{

View file

@ -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())
{
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);
}
if (ttr.params_list.params_list.Count > 0)
visit(ttr);
else
visit(ttr.name);
}
}
}

View file

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

View file

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

View file

@ -1,4 +1,4 @@
%COREVERSION%=0
%REVISION%=1247
%MINOR%=1
%REVISION%=1250
%COREVERSION%=0
%MAJOR%=3

View file

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

View file

@ -1 +1 @@
!define VERSION '3.1.0.1247'
!define VERSION '3.1.0.1250'

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

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

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

View file

@ -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,23 +8547,26 @@ 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)
{
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)
{
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)
{
return new indefinite_reference(dn as indefinite_definition_node, get_location(id_right));
@ -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)

View file

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

View file

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

View file

@ -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);
@ -26,7 +26,7 @@ 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);

View file

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

View file

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

View file

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

View file

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