public bool FindIEnumerableElementType(SyntaxTree.foreach_stmt _foreach_stmt, type_node tn, ref type_node elem_type) { var IEnstring = "System.Collections.IEnumerable"; compiled_type_node ctn = compiled_type_node.get_type_node(NetHelper.NetHelper.FindType(IEnstring)); if (tn is compiled_type_node || tn is compiled_generic_instance_type_node) // Если этот тип зашит в .NET // IEnumerable<integer>, Range(1,10), Dictionary<string,integer>: tn = compiled_type_node // IEnumerable<T>: tn = compiled_generic_instance_type_node // FibGen = class(IEnumerable,IEnumerator): tn = common_type_node, en = compiled_type_node // array of Person: tn = common_type_node { System.Type ct; if (tn is compiled_type_node) ct = (tn as compiled_type_node).compiled_type; else { var orig = (tn as compiled_generic_instance_type_node).original_generic as compiled_type_node; var pars = tn.instance_params; ct = orig.compiled_type; } Type r; var IEnTstring = "System.Collections.Generic.IEnumerable`1"; if (ct.ToString().StartsWith(IEnTstring)) r = ct; else r = ct.GetInterface(IEnTstring); if (r != null) { Type arg1 = r.GetGenericArguments().First(); // тип параметра IEnumerable var str = arg1.GetGenericArguments().Count(); if (tn is compiled_type_node) { elem_type = compiled_type_node.get_type_node(arg1); } else { if (arg1.GetGenericArguments().Count()>0) { elem_type = compiled_type_node.get_type_node(arg1.GetGenericTypeDefinition()); elem_type = elem_type.get_instance(tn.instance_params); // SSM 19/07/15 - работает!!! } else { var ip = tn.instance_params; //var Tname = ip[0].name; //elem_type = convert_strong(new SyntaxTree.named_type_reference(Tname, _foreach_stmt.in_what.source_context)); elem_type = ip[0]; } //elem_type.instance_params = tn.instance_params; //var ip = tn.instance_params; //var Tname = new string(tn.name.SkipWhile(c => c != '<').Skip(1).TakeWhile(c => c != ',' && c != '>').ToArray()); //var Tname = ip[0].name; //var Tname = "System.Collections.Generic.KeyValuePair'2"; // <integer,TClass> //elem_type = convert_strong(new SyntaxTree.named_type_reference(Tname, _foreach_stmt.in_what.source_context)); } return true; } else { if (tn.element_type != null) // значит, это массив любой размерности - 02.02.16 SSM - еще может быть множество set of T - 22.02.16 SSM { elem_type = tn.element_type; return true; } var ttt = tn.ImplementingInterfaces; foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces) { if (itn == ctn) { elem_type = SystemLibrary.SystemLibrary.object_type; return true; } } } } /*else if (tn is compiled_generic_instance_type_node) { var g = tn as compiled_generic_instance_type_node; var og = g.original_generic; var tt = og.ImplementingInterfaces; if (_foreach_stmt.type_name != null && _foreach_stmt.type_name.GetType()!=typeof(SyntaxTree.no_type_foreach)) elem_type = convert_strong(_foreach_stmt.type_name); else { var fn = tn.full_name; } return true; } */ else // если мы самостоятельно определяем этот тип - можно реализовать в PascalABC.NET только IEnumerable. // Сейчас уже можно!!!!! // Попытка реализовать IEnumerable<T> натыкается на необходимость определять GetEnumerator, возвращающий IEnumerator и IEnumerator<T> { if (tn == null || tn is null_type_node || tn.ImplementingInterfaces == null) return false; if (tn.element_type != null) // еще может быть множество set of T - 22.02.16 SSM { elem_type = tn.element_type; return true; } foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces) // Ищем интерфейс IEnumerable<T> и возвращаем T в качестве elem_type { if (itn is compiled_generic_instance_type_node) { var itnc = (itn as compiled_generic_instance_type_node); var tt = (itnc.original_generic as compiled_type_node).compiled_type; if (tt == typeof(System.Collections.Generic.IEnumerable<>)) { elem_type = itnc.generic_parameters[0] as common_type_node; return true; } } } foreach (SemanticTree.ITypeNode itn in tn.ImplementingInterfaces) // если не нашли - ищем интерфейс IEnumerable и возвращаем object в качестве elem_type { if (itn is compiled_type_node) { /*var itnc = (itn as compiled_type_node).compiled_type; if (itnc.IsGenericType) { var my = itnc.GetGenericTypeDefinition();// = typeof(System.Collections.Generic.IEnumerable<>) if (my == typeof(System.Collections.Generic.IEnumerable<>)) { var aarg1 = itnc.GetGenericArguments().First(); elem_type = compiled_type_node.get_type_node(aarg1); return true; } } else */ if (itn == ctn) { elem_type = SystemLibrary.SystemLibrary.object_type; return true; } } } } return false; }