pascalabcnet/TreeConverter/NetWrappers/NetHelper.cs
Бондарев Иван 3f520df65e Поддержка пространств имен в проектах
Возможность расширять пространства имен .NET
2017-10-03 20:18:37 +02:00

2202 lines
92 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (c) Ivan Bondarev, Stanislav Mihalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using PascalABCCompiler.SemanticTree;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using PascalABCCompiler.TreeConverter;
using PascalABCCompiler.TreeRealization;
namespace PascalABCCompiler.NetHelper
{
class TypeInfo
{
public Type type;
public string FullName;
public TypeInfo(Type type, string FullName)
{
this.type = type;
this.FullName = FullName;
}
}
class TypeNamespaceInfo
{
public TypeInfo type_info;
public using_namespace us_ns;
public TypeNamespaceInfo(TypeInfo type_info, using_namespace us_ns)
{
this.type_info = type_info;
this.us_ns = us_ns;
}
}
class FoundInfo
{
public bool exists;
public List<TypeNamespaceInfo> type_infos;
public FoundInfo(bool exists, TypeInfo TypeInfo=null, using_namespace un=null)
{
this.exists = exists;
if (exists)
{
type_infos = new List<TypeNamespaceInfo>();
type_infos.Add(new TypeNamespaceInfo(TypeInfo,un));
}
}
public TypeInfo GetTypeByNamespaceList(using_namespace_list unl)
{
foreach (TypeNamespaceInfo tni in type_infos)
{
foreach (using_namespace un in unl)
{
if (string.Compare(un.namespace_name, tni.us_ns.namespace_name, true) == 0)
{
return tni.type_info;
}
}
}
return null;
}
}
public class NetScope : SymbolTable.DotNETScope {
//private base_scope _up_scope;
private PascalABCCompiler.TreeRealization.using_namespace_list _unar;
internal System.Reflection.Assembly _assembly;
private SymbolTable.TreeConverterSymbolTable _tcst;
internal Type entry_type = null;
private List<Type> UnitTypes = null;
public NetScope(PascalABCCompiler.TreeRealization.using_namespace_list unar,System.Reflection.Assembly assembly,
SymbolTable.TreeConverterSymbolTable tcst) : base(tcst)
{
_unar=unar;
_assembly=assembly;
UnitTypes = NetHelper.init_namespaces(assembly);
if (UnitTypes.Count > 0)
{
entry_type = GetEntryType();
}
_tcst=tcst;
}
private Type GetEntryType()
{
if (_unar.Count > 0)
{
for (int i = 0; i < UnitTypes.Count; i++)
{
if (string.Compare(UnitTypes[i].Name, _unar[0].namespace_name, true) == 0)
return UnitTypes[i];
}
return UnitTypes[0];
}
else
{
return UnitTypes[0];
}
}
public Assembly Assembly
{
get
{
return _assembly;
}
}
public PascalABCCompiler.TreeRealization.using_namespace_list used_namespaces
{
get
{
return _unar;
}
set
{
_unar = value;
}
}
/*public override base_scope top_scope
{
get
{
return _up_scope;
}
}*/
public override SymbolInfoList Find(string name, SymbolTable.Scope CurrentScope)
{
SymbolInfoList si = null;
string full_ns = null;
if (NetHelper.IsNetNamespace(name, _unar, out full_ns) == true)
{
compiled_namespace_node cnn = compiled_namespace_node.get_compiled_namespace(full_ns, _tcst);//new compiled_namespace_node(full_ns, _tcst);
si = new SymbolInfoList(new SymbolInfoUnit(cnn));
}
else
{
//Type t = Type.GetType("System."+name,false,true);
Type t = null;
t = NetHelper.FindType(name, _unar);
if (t != null)
{
compiled_type_node ctn = compiled_type_node.get_type_node(t, _tcst);
si = new SymbolInfoList(new SymbolInfoUnit(ctn));
}
else
{
if (entry_type != null)
{
type_node pas_tn = NetHelper.FindCompiledPascalType(entry_type.Namespace + "." + name);
if (pas_tn != null)
{
si = new SymbolInfoList(new SymbolInfoUnit(pas_tn));
return si;
}
else
{
template_class tc = NetHelper.FindCompiledTemplateType(entry_type.Namespace + "." + name);
if (tc != null)
{
si = new SymbolInfoList(new SymbolInfoUnit(tc));
return si;
}
}
}
if (SemanticRules.AllowGlobalVisibilityForPABCDll && entry_type != null)
{
t = NetHelper.FindType(entry_type.Namespace + "." + name);
if (t != null) si = new SymbolInfoList(new SymbolInfoUnit(compiled_type_node.get_type_node(t)));
else
{
object[] attrs = entry_type.GetCustomAttributes(false);
for (int j = 0; j < attrs.Length; j++)
if (attrs[j].GetType().Name == PascalABCCompiler.TreeConverter.compiler_string_consts.global_attr_name)
{
si = NetHelper.FindName(entry_type, name);
if (si != null) break;
}
}
if (si == null && UnitTypes.Count > 1)
{
for (int j = 0; j < _unar.Count; j++)
{
t = in_type_list(_unar[j].namespace_name);
if (t != null)
{
si = NetHelper.FindName(t, name);
if (si != null)
break;
}
}
}
}
}
}
return si;
}
private Type in_type_list(string name)
{
for (int i = 1; i < UnitTypes.Count; i++)
{
if (string.Compare(UnitTypes[i].Name, name, true) == 0)
return UnitTypes[i];
}
return null;
}
}
public class NetTypeScope : SymbolTable.DotNETScope {
//private base_scope _up_scope;
private Type type_info;
public NetTypeScope(Type type_info,SymbolTable.DSSymbolTable tcst) : base(tcst)
{
this.type_info = type_info;
}
/*public override base_scope top_scope
{
get
{
return _up_scope;
}
}*/
public Type TypeInfo {
get {
return type_info;
}
set {
type_info = value;
}
}
public override SymbolInfoList Find(string name, SymbolTable.Scope CurrentScope)
{
return NetHelper.FindName(type_info, name);
}
}
public static class NetHelper {
private static Hashtable namespaces;
private static Hashtable types;
private static Dictionary<string,FoundInfo> type_search_cache;
private static Hashtable compiled_pascal_types;
/*private static Hashtable methods;
private static Hashtable properties;
private static Hashtable fields;*/
//ssyy-
//private static Hashtable interfaces;
//\ssyy-
private static Dictionary<Type, Dictionary<string, List<MemberInfo>>> members;
//private static Hashtable meth_nodes;
private static Dictionary<PropertyInfo, compiled_property_node> prop_nodes;
private static Hashtable field_nodes;
private static Hashtable constr_nodes;
private static Hashtable stand_types;
private static Hashtable type_handles;
private static Hashtable method_handles;
private static Hashtable constr_handles;
private static Hashtable field_handles;
private static Hashtable assemblies;
private static Hashtable special_types;
private static Hashtable ns_types;
private static Type memberInfo;
private static Hashtable namespace_assemblies;
public static Hashtable cur_used_assemblies;
private static Hashtable cached_type_extensions;
public static Type DelegateType;
public static Type EnumType;
public static Type ArrayType;
public static Type void_type;
public static Type MulticastDelegateType;
public static Type ExtensionAttributeType;
public static MethodInfo AddToDictionaryMethod;
public static bool UsePABCRtl;
public static Assembly SystemCoreAssembly;
private static Dictionary<Type,MethodInfo[]> extension_methods = new Dictionary<Type,MethodInfo[]>();
private static Dictionary<Type,List<MethodInfo>> type_extensions = new Dictionary<Type, List<MethodInfo>>();
private static Dictionary<Type, Type> arrays_with_extension_methods = new Dictionary<Type, Type>();
private static Dictionary<Type, Type> generics_with_extension_methods = new Dictionary<Type, Type>();
private static Dictionary<int, List<MethodInfo>> generic_array_type_extensions = new Dictionary<int, List<MethodInfo>>();
private static List<MethodInfo> generic_parameter_type_extensions = new List<MethodInfo>();
public static Type PABCSystemType = null;
public static Type PT4Type = null;
public static Type StringType = typeof(string);
public static Dictionary<string, List<int>> generics_names = new Dictionary<string, List<int>>();
private static Dictionary<string, MemberInfo> member_cache = new Dictionary<string, MemberInfo>();
public static void reset()
{
if (cur_used_assemblies == null)
cur_used_assemblies = new Hashtable();
cur_used_assemblies.Clear();
cur_used_assemblies[typeof(string).Assembly] = typeof(string).Assembly;
cur_used_assemblies[typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly] = typeof(Microsoft.CSharp.CSharpCodeProvider).Assembly;
type_search_cache.Clear();
}
private static Hashtable ass_name_cache;
private static Hashtable file_dates;
public static bool IsAssemblyChanged(string name)
{
if (name == null) return false;
Assembly a = ass_name_cache[name] as Assembly;
if (a != null)
{
if (System.IO.File.GetLastWriteTime(name) != (DateTime)file_dates[a])
return true;
return false;
}
else
return false;
}
public static Assembly LoadAssembly(string name)
{
if (name == null) return null;
Assembly a = ass_name_cache[name] as Assembly;
if (a != null)
{
if (System.IO.File.GetLastWriteTime(name) == (DateTime)file_dates[a])
return a;
namespace_assemblies.Remove(a);
assemblies.Remove(a);
cur_used_assemblies.Remove(a);
ns_types.Clear();
Type[] tarr = a.GetTypes();
foreach(Type t in tarr)
{
if (t.Namespace != "" && t.Namespace != null)
{
string s = t.Namespace;
int pos = s.LastIndexOf('.');
namespaces.Remove(s);
while (pos != -1)
{
s = s.Substring(0,pos);
pos = s.LastIndexOf('.');
//if (pos == -1)
namespaces.Remove(s);
}
}
if (t.Name.StartsWith("%"))
{
types.Remove(t.Namespace+"."+t.Name.Substring(1));
}
else
types.Remove(t.FullName);
if (t == ExtensionAttributeType)
{
ExtensionAttributeType = null;
extension_methods.Clear();
}
if (type_extensions.ContainsKey(t))
type_extensions.Remove(t);
}
}
//if (!System.IO.Path.GetFileName(name).ToLower().Contains("microsoft.directx"))
try
{
System.IO.FileStream fs = System.IO.File.OpenRead(name);
byte[] buf = new byte[fs.Length];
fs.Read(buf, 0, (int)fs.Length);
fs.Close();
curr_inited_assm_path = name;
a = System.Reflection.Assembly.Load(buf);
a.GetTypes();
buf = null;
//Thread th = new Thread(new ThreadStart(collect_internal));
//th.Start();
}
catch (Exception ex)
{
a = System.Reflection.Assembly.LoadFrom(name);
}
ass_name_cache[name] = a;
file_dates[a] = System.IO.File.GetLastWriteTime(name);
return a;
}
private static void collect_internal()
{
}
public static Hashtable entry_types = new Hashtable();
private static string curr_inited_assm_path = null;
public static List<Type> init_namespaces(System.Reflection.Assembly _assembly)
{
Assembly assembly = (Assembly)assemblies[_assembly];
List<string> nss = new List<string>();
cur_used_assemblies[_assembly] = _assembly;
Type entry_type = null;
List<Type> unit_types = entry_types[_assembly] as List<Type>;
if (unit_types == null)
unit_types = new List<Type>();
if (assembly == null)
{
Type[] tarr = _assembly.GetTypes();
//Hashtable ns_ht = new Hashtable(CaseInsensitiveHashCodeProvider.Default,CaseInsensitiveComparer.Default);
Hashtable ns_ht = new Hashtable(StringComparer.CurrentCultureIgnoreCase);
foreach (Type t in tarr)
{
if (t.IsNotPublic)
continue;
if (t.Namespace != "" && t.Namespace != null && t.FullName.IndexOf('$') == -1)
{
string s = t.Namespace;
int pos = s.LastIndexOf('.');
//if (pos == -1)
//if (namespaces[s] == null) ns_ht.Add(s,s);
ns_ht[s] = s;
namespaces[s] = t;
if (pos != -1)
{
string[] sub_ns_arr = s.Split('.');
string sub_ns_str = sub_ns_arr[sub_ns_arr.Length - 1];
namespaces[sub_ns_str] = t;
ns_ht[sub_ns_str] = s;
int ind = sub_ns_arr.Length - 2;
while (ind != 0)
{
sub_ns_str = sub_ns_arr[ind] + "." + sub_ns_str;
ind--;
}
}
while (pos != -1)
{
s = s.Substring(0, pos);
pos = s.LastIndexOf('.');
//if (pos == -1)
if (namespaces[s] == null)
namespaces[s] = t;
ns_ht[s] = s;
}
}
TypeInfo ti = new TypeInfo(t, t.FullName);
types[t.FullName] = ti;
string short_name = t.Name;
object o2 = types[short_name];
if (o2 == null)
types[short_name] = ti;
else
{
if (o2 is TypeInfo)
{
List<TypeInfo> type_lst = new List<TypeInfo>();
type_lst.Add(o2 as TypeInfo);
type_lst.Add(ti);
types[short_name] = type_lst;
}
else if (o2 is List<TypeInfo>)
{
(o2 as List<TypeInfo>).Add(ti);
}
}
AddGenericInfo(t);
if (ExtensionAttributeType != null && t.GetCustomAttributes(ExtensionAttributeType, false).Length > 0)
{
MethodInfo[] meths = t.GetMethods(BindingFlags.Public | BindingFlags.Static);
List<MethodInfo> ext_meths = new List<MethodInfo>();
if (!extension_methods.ContainsKey(t))
{
foreach (MethodInfo mi in meths)
if (mi.GetCustomAttributes(ExtensionAttributeType, false).Length > 0)
{
ext_meths.Add(mi);
ParameterInfo[] prms = mi.GetParameters();
if (prms.Length > 0)
{
List<MethodInfo> mths = null;
List<MethodInfo> mths2 = null;
Type tmp = prms[0].ParameterType;
if (tmp.IsGenericType)
{
tmp = tmp.GetGenericTypeDefinition();
}
if (!type_extensions.TryGetValue(tmp, out mths))
{
mths = new List<MethodInfo>();
type_extensions.Add(tmp, mths);
}
mths.Add(mi);
if (tmp.IsArray && !generic_array_type_extensions.TryGetValue(tmp.GetArrayRank(), out mths2))
{
mths2 = new List<MethodInfo>();
generic_array_type_extensions.Add(tmp.GetArrayRank(), mths2);
}
if (mths2 != null)
mths2.Add(mi);
Dictionary<string, List<MemberInfo>> mht;
if (members.TryGetValue(tmp, out mht))
{
List<MemberInfo> mis2 = null;
string name = compiler_string_consts.GetNETOperName(mi.Name);
if (name == null)
name = mi.Name;
if (!mht.TryGetValue(name, out mis2))
{
mis2 = new List<MemberInfo>();
mht.Add(name, mis2);
}
if (!mis2.Contains(mi))
mis2.Add(mi);
}
if (tmp.IsGenericParameter && !generic_parameter_type_extensions.Contains(mi))
{
generic_parameter_type_extensions.Add(mi);
foreach (Type tt in members.Keys)
{
if (members.TryGetValue(tt, out mht))
{
List<MemberInfo> mis2 = null;
string name = compiler_string_consts.GetNETOperName(mi.Name);
if (name == null)
name = mi.Name;
if (!mht.TryGetValue(name, out mis2))
{
mis2 = new List<MemberInfo>();
mht.Add(name, mis2);
}
if (!mis2.Contains(mi))
mis2.Add(mi);
}
}
}
foreach (Type arr_t in arrays_with_extension_methods.Keys)
{
if (members.TryGetValue(arr_t, out mht))
{
List<MemberInfo> mis2 = null;
string name = compiler_string_consts.GetNETOperName(mi.Name);
if (name == null)
name = mi.Name;
if (!mht.TryGetValue(name, out mis2))
{
mis2 = new List<MemberInfo>();
mht.Add(name, mis2);
}
if (!mis2.Contains(mi))
mis2.Add(mi);
}
}
foreach (Type gen_t in generics_with_extension_methods.Keys)
{
if (members.TryGetValue(gen_t, out mht))
{
List<MemberInfo> mis2 = null;
string name = compiler_string_consts.GetNETOperName(mi.Name);
if (name == null)
name = mi.Name;
if (!mht.TryGetValue(name, out mis2))
{
mis2 = new List<MemberInfo>();
mht.Add(name, mis2);
}
if (!mis2.Contains(mi))
mis2.Add(mi);
}
}
}
}
extension_methods.Add(t, ext_meths.ToArray());
}
}
if (t.Name == t.Namespace)
{
object[] attrs = t.GetCustomAttributes(false);
foreach (Attribute attr in attrs)
{
if (attr.GetType().Name == PascalABCCompiler.TreeConverter.compiler_string_consts.global_attr_name)
{
entry_type = t;
unit_types.Insert(0, t);
entry_types[_assembly] = unit_types;
break;
}
else if (attr.GetType().Name == PascalABCCompiler.TreeConverter.compiler_string_consts.class_unit_attr_name)
{
if (_assembly.ManifestModule.ScopeName == compiler_string_consts.pabc_rtl_dll_name)
{
if (t.Name == "PABCSystem")
PABCSystemType = t;
else if (t.Name == "PT4")
PT4Type = t;
}
unit_types.Add(t);
break;
}
}
}
else if (t.Name.StartsWith("%"))
{
object[] attrs = t.GetCustomAttributes(false);
if (attrs.Length == 1)
{
Type attr_t = attrs[0].GetType();
if (attr_t.FullName == compiler_string_consts.file_of_attr_name)
{
object o = attr_t.GetField("Type", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
if (o is Type)
attr_t = o as Type;
else
attr_t = _assembly.GetType(o as string, false);
if (PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
type_node tn = CreatePascalType(attr_t);
if (tn != null)
tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(tn, null);
else
tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(compiled_type_node.get_type_node(attr_t), null);
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = tn;
}
else
{
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = t;
}
}
else if (attr_t.FullName == compiler_string_consts.set_of_attr_name)
{
object o = attr_t.GetField("Type", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
if (o is Type)
attr_t = o as Type;
else
{
attr_t = t.Assembly.GetType(o as string, false);
}
if (PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
type_node tn = CreatePascalType(attr_t);
if (tn != null)
tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(tn, null);
else
tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(compiled_type_node.get_type_node(attr_t), null);
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = tn;
}
else
{
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = t;
}
}
else if (attr_t.FullName == compiler_string_consts.short_string_attr_name)
{
int len = (int)attr_t.GetField("Length", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
if (PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
type_node tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_short_string_type(len, null);
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = tn;
}
else
{
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = t;
}
}
else if (attr_t.FullName == compiler_string_consts.template_class_attr_name)
{
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = t;
}
else if (attr_t.FullName == compiler_string_consts.type_synonim_attr_name)
{
object o = attr_t.GetField("Type", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
if (o is Type)
attr_t = o as Type;
else
attr_t = _assembly.GetType(o as string, false);
if (attr_t != null)
{
type_node tn = CreatePascalType(attr_t);
if (tn != null)
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = tn;
else
types[t.Namespace + "." + t.Name.Substring(1)] = new TypeInfo(attr_t, attr_t.FullName);
}
}
}
}
}
namespace_assemblies[_assembly] = ns_ht;
assemblies[_assembly] = _assembly;
}
return unit_types;
}
private static template_class CreateTemplateClassType(Type t)
{
if (t == null)
return null;
object[] attrs = t.GetCustomAttributes(false);
if (attrs.Length == 1)
{
Type attr_t = attrs[0].GetType();
byte[] tree = (byte[])attr_t.GetField("Tree", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
return PascalABCCompiler.TreeConverter.compilation_context.instance.create_template_class(t.FullName, tree);
}
return null;
}
private static type_node CreatePascalType(Type t)
{
if (t == null)
return null;
object[] attrs = t.GetCustomAttributes(false);
bool not_pascal_type = false;
if (attrs.Length == 1)
{
Type attr_t = attrs[0].GetType();
if (attr_t.FullName == compiler_string_consts.file_of_attr_name)
{
object o = attr_t.GetField("Type", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
if (o is Type)
attr_t = o as Type;
else
{
attr_t = t.Assembly.GetType(o as string, false);
if (attr_t != null)
{
type_node tn = CreatePascalType(attr_t);
if (tn != null)
return PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(tn, null);
}
}
return PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(compiled_type_node.get_type_node(attr_t), null);
}
else if (attr_t.FullName == compiler_string_consts.set_of_attr_name)
{
object o = attr_t.GetField("Type", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
if (o is Type)
attr_t = o as Type;
else
{
attr_t = t.Assembly.GetType(o as string, false);
if (attr_t != null)
{
type_node tn = CreatePascalType(attr_t);
if (tn != null)
return PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(tn, null);
}
}
return PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(compiled_type_node.get_type_node(attr_t), null);
}
else if (attr_t.FullName == compiler_string_consts.short_string_attr_name)
{
int len = (int)attr_t.GetField("Length", BindingFlags.Public | BindingFlags.Instance).GetValue(attrs[0]);
return PascalABCCompiler.TreeConverter.compilation_context.instance.create_short_string_type(len, null);
}
else if (attr_t.FullName == compiler_string_consts.template_class_attr_name)
{
return null;
}
else
not_pascal_type = true;
}
else
not_pascal_type = true;
if (not_pascal_type)
{
if (t.IsPointer)
{
if (t.GetElementType() == void_type)
return SystemLibrary.SystemLibrary.pointer_type;
else
{
type_node elem_t = CreatePascalType(t.GetElementType());
return elem_t.ref_type;
}
}
else
return compiled_type_node.get_type_node(t, SystemLibrary.SystemLibrary.syn_visitor.SymbolTable);
}
return null;
}
public static bool IsEntryType(Type t)
{
object[] attrs = t.GetCustomAttributes(false);
for (int j=0; j<attrs.Length; j++)
if (attrs[j].GetType().Name == PascalABCCompiler.TreeConverter.compiler_string_consts.global_attr_name
|| attrs[j].GetType().Name == PascalABCCompiler.TreeConverter.compiler_string_consts.class_unit_attr_name)
{
return true;
}
return false;
}
public static bool NamespaceExists(string Namespace)
{
Type t = (Type)namespaces[Namespace];
if (t != null && cur_used_assemblies.ContainsKey(t.Assembly)) return true;
foreach (Assembly a in namespace_assemblies.Keys)
if (cur_used_assemblies.ContainsKey(a) && (namespace_assemblies[a] as Hashtable).ContainsKey(Namespace))
return true;
return false;
}
static NetHelper()
{
//scope = new NetScope(null,null);
//namespaces = new Hashtable(1024, CaseInsensitiveHashCodeProvider.Default,CaseInsensitiveComparer.Default);
//ssyy-
//interfaces = new Hashtable();
//\ssyy-
//types = new Hashtable(1024, CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
types = new Hashtable(8096, StringComparer.CurrentCultureIgnoreCase);
compiled_pascal_types = new Hashtable(1024, StringComparer.CurrentCultureIgnoreCase);
namespaces = new Hashtable(1024, StringComparer.CurrentCultureIgnoreCase);
ass_name_cache = new Hashtable(1024, StringComparer.CurrentCultureIgnoreCase);
//ass_name_cache = new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
file_dates = new Hashtable();
//methods = new Hashtable();
//properties = new Hashtable();
members = new Dictionary<Type, Dictionary<string, List<MemberInfo>>>(128);
//fields = new Hashtable();
assemblies = new Hashtable();
//meth_nodes = new Hashtable();
prop_nodes = new Dictionary<PropertyInfo,compiled_property_node>();
field_nodes = new Hashtable();
constr_nodes = new Hashtable();
stand_types = new Hashtable();
type_handles = new Hashtable();
method_handles = new Hashtable();
constr_handles = new Hashtable();
field_handles = new Hashtable();
special_types = new Hashtable();
type_search_cache = new Dictionary<string,FoundInfo>(300);
cached_type_extensions = new Hashtable();
namespace_assemblies = new Hashtable();
cur_used_assemblies = new Hashtable();
//ns_types = new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
ns_types = new Hashtable(StringComparer.CurrentCultureIgnoreCase);
memberInfo = typeof(MemberInfo);
stand_types[typeof(int)] = stand_types;
stand_types[typeof(byte)] = stand_types;
stand_types[typeof(bool)] = stand_types;
stand_types[typeof(sbyte)] = stand_types;
stand_types[typeof(short)] = stand_types;
stand_types[typeof(ushort)] = stand_types;
stand_types[typeof(uint)] = stand_types;
stand_types[typeof(long)] = stand_types;
stand_types[typeof(ulong)] = stand_types;
stand_types[typeof(char)] = stand_types;
stand_types[typeof(float)] = stand_types;
stand_types[typeof(double)] = stand_types;
//stand_types[typeof(decimal)]=stand_types;
//stand_types[NetHelper.void_ptr_type] = stand_types;
DelegateType = typeof(Delegate);
MulticastDelegateType = typeof(MulticastDelegate);
void_type = typeof(void);
AddSpecialType(void_ptr_type);
AppDomain.CurrentDomain.AssemblyResolve +=new ResolveEventHandler(CurrentDomain_AssemblyResolve);
ExtensionAttributeType = typeof(System.Runtime.CompilerServices.ExtensionAttribute);
SystemCoreAssembly = ExtensionAttributeType.Assembly;
EnumType = typeof(Enum);
ArrayType = typeof(Array);
AddToDictionaryMethod = typeof(Dictionary<string, object>).GetMethod("Add");
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
try
{
if (curr_inited_assm_path != null)
{
Assembly assm = null;
string path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(curr_inited_assm_path), args.Name.Substring(0, args.Name.IndexOf(",")) + ".dll");
if (System.IO.File.Exists(path))
assm = LoadAssembly(path);
curr_inited_assm_path = null;
//return LoadAssembly(args.Name);
return assm;
}
return null;
}
catch
{
return null;
}
}
private static void AddSpecialType(Type t)
{
special_types[t.MetadataToken] = t;
}
public static bool IsStandType(Type t)
{
if (stand_types[t] != null) return true;
return false;
}
public static bool IsNetNamespace(string name, Type tt = null)
{
Type t = null;
if (tt != null)
t = tt;
else
t = namespaces[name] as Type;
if (t != null && cur_used_assemblies.ContainsKey(t.Assembly)) return true;
foreach (Assembly a in namespace_assemblies.Keys)
if (cur_used_assemblies.ContainsKey(a) && (namespace_assemblies[a] as Hashtable).ContainsKey(name)) return true;
return false;
}
public static bool IsNetNamespace(string name,PascalABCCompiler.TreeRealization.using_namespace_list _unar, out string full_ns)
{
Type t = namespaces[name] as Type;
full_ns = name;
if (t != null)
{
if (PABCSystemType != null && t.Assembly == PABCSystemType.Assembly && !UsePABCRtl)
return false;
Type tt = t;
if (string.Compare(t.Namespace, name, true) == 0)
{
full_ns = t.Namespace;
return true;
}
for (int i = 0; i < _unar.Count; i++)
{
string full_name = _unar[i].namespace_name + "." + name;
if (string.Compare(full_name, t.Namespace, true) == 0)
{
full_ns = full_name;
return IsNetNamespace(name, t);
}
}
for (int i = 0; i < _unar.Count; i++)
{
string full_name = _unar[i].namespace_name + "." + name;
t = namespaces[full_name] as Type;
if (t != null)
{
full_ns = full_name;
return IsNetNamespace(full_ns, t);
}
}
if (tt.Namespace.IndexOf(name, 0, StringComparison.OrdinalIgnoreCase) == 0)
{
return true;
}
}
return false;
}
public static Type void_ptr_type
{
get
{
if(SemanticRules.PoinerRealization == PoinerRealization.IntPtr)
return FindTypeOrCreate(compiler_string_consts.pointer_net_type_name_intptr);
return FindTypeOrCreate(compiler_string_consts.pointer_net_type_name_void);
}
}
public static IEnumerable<MemberInfo> GetExtensionMethods(Type t)
{
List<MethodInfo> meths = null;
if (SystemCoreAssembly == null || !cur_used_assemblies.ContainsKey(SystemCoreAssembly))
return new List<MemberInfo>();
if (type_extensions.TryGetValue(t, out meths) || t.IsGenericType && type_extensions.TryGetValue(t.GetGenericTypeDefinition(), out meths))
{
//return meths.ToArray();
}
else
{
meths = new List<MethodInfo>();
}
//meths = new List<MethodInfo>();
Type[] tt = t.GetInterfaces();
for (int i = 0; i < tt.Length; i++)
{
meths.AddRange((MethodInfo[])GetExtensionMethodsNoRecursive(tt[i]));
}
if (t.BaseType != null)
meths.AddRange((MethodInfo[])GetExtensionMethods(t.BaseType));
return meths.ToArray();
}
private static IEnumerable<MemberInfo> GetExtensionMethodsNoRecursive(Type t)
{
List<MethodInfo> meths = null;
if (type_extensions.TryGetValue(t, out meths) || t.IsGenericType && type_extensions.TryGetValue(t.GetGenericTypeDefinition(), out meths))
{
return meths.ToArray();
}
return new List<MethodInfo>().ToArray();
}
private static function_node get_conversion(compiled_type_node in_type,compiled_type_node from,
compiled_type_node to,string op_name, NetTypeScope scope)
{
//MethodInfo[] mia = in_type.compiled_type.GetMethods();
List<MemberInfo> mia = GetMembers(in_type.compiled_type, op_name);
foreach (MemberInfo mbi in mia)
{
if (!(mbi is MethodInfo))
continue;
MethodInfo mi = mbi as MethodInfo;
if (mi.ReturnType != to.compiled_type)
{
continue;
}
ParameterInfo[] piarr = mi.GetParameters();
if (piarr.Length != 1)
{
continue;
}
if (piarr[0].ParameterType != from.compiled_type)
{
continue;
}
return compiled_function_node.get_compiled_method(mi);
}
if (scope != null)
{
SymbolInfoList si = scope.FindOnlyInType(op_name, scope);
if(si != null)
foreach(SymbolInfoUnit si_unit in si.InfoUnitList)
{
if (si_unit.sym_info is common_namespace_function_node)
{
function_node fn = si_unit.sym_info as function_node;
if ((fn.return_value_type == to || fn.return_value_type.original_generic == to) &&
fn.parameters.Count == 1 &&
(fn.parameters[0].type == from || fn.parameters[0].type.original_generic == from))
{
return fn;
}
}
}
}
return null;
}
public static function_node get_implicit_conversion(compiled_type_node in_type, compiled_type_node from,
compiled_type_node to, NetTypeScope scope)
{
return get_conversion(in_type, from, to, compiler_string_consts.implicit_operator_name, scope);
}
public static function_node get_explicit_conversion(compiled_type_node in_type, compiled_type_node from,
compiled_type_node to, NetTypeScope scope)
{
return get_conversion(in_type, from, to, compiler_string_consts.explicit_operator_name, scope);
}
public static compiled_type_node get_array_type(compiled_type_node element_type)
{
return (compiled_type_node.get_type_node(element_type.compiled_type.MakeArrayType()));
}
public static compiled_type_node get_array_type(compiled_type_node element_type, int rank)
{
if (rank == 1)
return (compiled_type_node.get_type_node(element_type.compiled_type.MakeArrayType()));
else
return (compiled_type_node.get_type_node(element_type.compiled_type.MakeArrayType(rank)));
}
public static string[] GetNamespaces(Assembly a)
{
Hashtable ht = (Hashtable)namespace_assemblies[a];
List<string> lst = new List<string>();
foreach (string s in ht.Values)
//if (s.IndexOf('.') == -1)
lst.Add(s);
return lst.ToArray();
}
public static void FormBaseInterfacesList(Type t, List<Type> interfaces)
{
if (interfaces.IndexOf(t) < 0)
{
interfaces.Add(t);
Type[] inters = t.GetInterfaces();
int count = inters.Length;
for (int i = inters.Length - 1; i > -1; --i)
{
FormBaseInterfacesList(inters[i], interfaces);
}
}
}
public static bool IsExtensionMethod(MethodInfo mi)
{
if (ExtensionAttributeType != null && mi.GetCustomAttributes(ExtensionAttributeType, false).Length > 0)
return true;
return false;
}
public static List<MemberInfo> GetMembers(Type t, string name)
{
Dictionary<string, List<MemberInfo>> mht = null;
if (members.TryGetValue(t, out mht))
{
List<MemberInfo> mis2 = null;
if (!mht.TryGetValue(name, out mis2))
{
return EmptyMemberInfoList;
}
return mis2;
}
else
{
BindingFlags bf = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic;
MemberInfo[] mis;
if (t.IsInterface)
{
List<Type> all_interfaces = new List<Type>();
FormBaseInterfacesList(t, all_interfaces);
List<MemberInfo> mem_info = new List<MemberInfo>();
foreach (Type interf in all_interfaces)
{
mem_info.AddRange(interf.GetMembers(bf));
}
mem_info.AddRange(typeof(object).GetMembers(bf));
mis = mem_info.ToArray();
}
else
{
mis = t.GetMembers(bf);
}
//(ssyy) DarkStar, что за предупреждение по следующей строке?
var ht = new Dictionary<string,List<MemberInfo>>(StringComparer.CurrentCultureIgnoreCase);
//(ssyy) DarkStar, может быть эффективнее слить следующие 2 цикла в один?
foreach (MemberInfo mi2 in mis)
{
//Console.WriteLine(mi2.Name.ToLower());
string s = mi2.Name;//.ToLower();
if (!ht.ContainsKey(s))
ht[s] = new List<MemberInfo>();
}
foreach (MemberInfo mi in mis)
{
ht[mi.Name].Add(mi);
}
if (ExtensionAttributeType != null)
{
List<MethodInfo> meths = null;
Type tmp_t = t;
if (tmp_t.IsArray)
arrays_with_extension_methods[tmp_t] = tmp_t;
if (tmp_t.IsGenericTypeDefinition)
generics_with_extension_methods[tmp_t] = tmp_t;
cached_type_extensions[t] = t;
while (tmp_t != null)
{
List<MethodInfo> meths1 = null;
List<MethodInfo> meths2 = null;
List<MethodInfo> meths3 = generic_parameter_type_extensions;
if (tmp_t.IsGenericType && !tmp_t.IsGenericTypeDefinition)
type_extensions.TryGetValue(tmp_t.GetGenericTypeDefinition(), out meths1);
if (tmp_t.IsArray)
generic_array_type_extensions.TryGetValue(tmp_t.GetArrayRank(), out meths2);
if (type_extensions.TryGetValue(tmp_t, out meths) || meths1 != null || meths2 != null || meths3 != null)
{
List<MethodInfo> all_meths = new List<MethodInfo>();
if (meths != null)
all_meths.AddRange(meths);
if (meths1 != null)
all_meths.AddRange(meths1);
if (meths2 != null)
all_meths.AddRange(meths2);
if (meths3 != null)
all_meths.AddRange(meths3);
foreach (MethodInfo mi in all_meths)
{
if (cur_used_assemblies.ContainsKey(mi.DeclaringType.Assembly))
{
List<MemberInfo> al = null;
string s = compiler_string_consts.GetNETOperName(mi.Name);
if (s == null)
s = mi.Name;
if (!ht.TryGetValue(s, out al))
{
al = new List<MemberInfo>();
ht[s] = al;
}
al.Insert(0, mi);
}
}
}
tmp_t = tmp_t.BaseType;
}
Type[] intfs = t.GetInterfaces();
foreach (Type intf_t in intfs)
{
Type tmp = intf_t;
if (tmp.IsGenericType)
tmp = tmp.GetGenericTypeDefinition();
if (type_extensions.TryGetValue(tmp, out meths))
{
foreach (MethodInfo mi in meths)
{
if (cur_used_assemblies.ContainsKey(mi.DeclaringType.Assembly))
{
List<MemberInfo> al = null;
if (!ht.TryGetValue(mi.Name, out al))
{
al = new List<MemberInfo>();
ht[mi.Name] = al;
}
al.Insert(0,mi);
}
}
}
}
}
members[t] = ht;
List<MemberInfo> lst = null;
if (!ht.TryGetValue(name, out lst))
return EmptyMemberInfoList;
return lst;
}
}
private static List<MemberInfo> EmptyMemberInfoList = new List<MemberInfo>();
//(ssyy) Является ли член класса видимым.
public static field_access_level get_access_level(MemberInfo mi)
{
field_access_level amod = field_access_level.fal_public;
switch (mi.MemberType)
{
case MemberTypes.Constructor:
case MemberTypes.Method:
{
MethodBase mb = mi as MethodBase;
MethodAttributes attrs = mb.Attributes;
if (attrs == (attrs | MethodAttributes.Public))
{
amod = field_access_level.fal_public;
}
else
{
if ((attrs == (attrs | MethodAttributes.Family) ||
attrs == (attrs | MethodAttributes.FamORAssem)) &&
((mi.MemberType == MemberTypes.Constructor) ? true : (attrs != (attrs | MethodAttributes.SpecialName))))
{
amod = field_access_level.fal_protected;
}
else
{
amod = field_access_level.fal_private;
}
}
}
break;
case MemberTypes.Field:
FieldInfo fi = mi as FieldInfo;
if (fi.Attributes == (fi.Attributes | FieldAttributes.Public)
&& (fi.Attributes != (fi.Attributes | FieldAttributes.SpecialName)))
{
amod = field_access_level.fal_public;
}
else
{
if (fi.Attributes == (fi.Attributes | FieldAttributes.Family)
|| fi.Attributes == (fi.Attributes | FieldAttributes.FamORAssem))
{
amod = field_access_level.fal_protected;
}
else
{
amod = field_access_level.fal_private;
}
}
break;
case MemberTypes.Property:
//PropertyInfo pi = mi as PropertyInfo;
MethodInfo mi2 = GetAnyAccessor(mi as PropertyInfo);
if (mi2 != null)
if (mi2.Attributes == (mi2.Attributes | MethodAttributes.Public))
{
amod = field_access_level.fal_public;
}
else
{
if ((mi2.Attributes == (mi2.Attributes | MethodAttributes.Family) ||
mi2.Attributes == (mi2.Attributes | MethodAttributes.FamORAssem)))
{
amod = field_access_level.fal_protected;
}
else
{
amod = field_access_level.fal_private;
}
}
break;
}
return amod;
}
public static bool is_visible(MemberInfo mi)
{
field_access_level amod = get_access_level(mi);
if (amod == field_access_level.fal_public)
{
return true;
}
if (amod == field_access_level.fal_private)
{
return false;
}
common_type_node curr_type = SystemLibrary.SystemLibrary.syn_visitor.context.converted_type;
compiled_type_node comp_node = compiled_type_node.get_type_node(mi.DeclaringType);
return curr_type != null && type_table.is_derived(comp_node, curr_type);
}
public static SymbolInfoList GetConstructor(Type t)
{
ConstructorInfo[] constrs = t.GetConstructors(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
SymbolInfoUnit si = null;
SymbolInfoList res_si = null;
foreach (ConstructorInfo ci in constrs)
{
field_access_level fal = get_access_level(ci);
if (fal != field_access_level.fal_private && fal != field_access_level.fal_internal)
{
si = new SymbolInfoUnit(compiled_constructor_node.get_compiled_constructor(ci));
if (res_si == null)
res_si = new SymbolInfoList();
res_si.Add(si);
}
}
return res_si;
}
public static bool HasFlagAttribute(Type t)
{
return t.GetCustomAttributes(typeof(FlagsAttribute), true).Length != 0;
}
public static bool IsParamsParameter(ParameterInfo pi)
{
return pi.GetCustomAttributes(typeof(ParamArrayAttribute), true).Length > 0;
}
public static bool IsType(string name)
{
return FindType(name) != null;
}
public static SymbolInfoList FindNameIncludeProtected(Type t, string name)
{
if (name == null) return null;
if (name == compiler_string_consts.assign_name) return null;
string s = compiler_string_consts.GetNETOperName(name);
if (s != null)
{
if (IsStandType(t)) return null;
name = s;
}
SymbolInfoList si=null;
List<MemberInfo> mis = GetMembers(t,name);
foreach (MemberInfo mi in mis)
{
if (mi.DeclaringType != null && PABCSystemType != null && mi.DeclaringType.Assembly == PABCSystemType.Assembly && !UsePABCRtl)
continue;
field_access_level fal = get_access_level(mi);
if (fal != field_access_level.fal_private && fal != field_access_level.fal_internal)
{
SymbolInfoUnit temp = null;
switch (mi.MemberType)
{
case MemberTypes.Method:
temp = new SymbolInfoUnit(compiled_function_node.get_compiled_method((MethodInfo)mi));
break;
case MemberTypes.Constructor:
temp = new SymbolInfoUnit(compiled_constructor_node.get_compiled_constructor((ConstructorInfo)mi));
break;
case MemberTypes.Property:
temp = new SymbolInfoUnit(GetPropertyNode((PropertyInfo)mi));
break;
case MemberTypes.Field:
temp = GetSymbolInfoForFieldNode((FieldInfo)mi);
break;
case MemberTypes.Event:
temp = new SymbolInfoUnit(GetEvent((EventInfo)mi));
break;
default:
continue;
}
if (si == null)
si = new SymbolInfoList();
si.InfoUnitList.Insert(0, temp);
}
}
Type nested_t = null;
foreach (Type nt in t.GetNestedTypes())
{
if (string.Compare(nt.Name, name, true) == 0)
{
nested_t = nt;
break;
}
}
if (nested_t != null)
{
SymbolInfoUnit temp = new SymbolInfoUnit(compiled_type_node.get_type_node(nested_t));
if (si == null)
si = new SymbolInfoList();
si.InfoUnitList.Insert(0, temp);
}
return si;
}
public static SymbolInfoList FindName(Type t, string name)
{
if (name == null) return null;
if (name == compiler_string_consts.assign_name) return null;
string s = compiler_string_consts.GetNETOperName(name);
string tmp_name = name;
if (s != null)
{
if (IsStandType(t)) return null;
if (t != NetHelper.PABCSystemType)
name = s;
}
SymbolInfoList si = null;
List<MemberInfo> mis = GetMembers(t, name);
//(ssyy) Изменил алгоритм.
//У нас некоторые алгоритмы базируются на том, что возвращённые
//сущности будут одной природы (например, все - методы). Это неверно,
//так как в случае наличия функции Ident и поля ident оба должны попасть
//в список.
//TODO: проанализировать и изменить алгоритмы, использующие поиск.
//List<SymbolInfo> si_list = new List<SymbolInfo>();
foreach (MemberInfo mi in mis)
{
if (mi.DeclaringType != null && PABCSystemType != null && mi.DeclaringType.Assembly == PABCSystemType.Assembly && !UsePABCRtl)
continue;
if (is_visible(mi))
{
SymbolInfoUnit temp = null;
switch (mi.MemberType)
{
case MemberTypes.Method:
temp = new SymbolInfoUnit(compiled_function_node.get_compiled_method(mi as MethodInfo));
break;
case MemberTypes.Constructor:
temp = new SymbolInfoUnit(compiled_constructor_node.get_compiled_constructor(mi as ConstructorInfo));
break;
case MemberTypes.Property:
temp = new SymbolInfoUnit(GetPropertyNode(mi as PropertyInfo));
break;
case MemberTypes.Field:
temp = GetSymbolInfoForFieldNode(mi as FieldInfo);
break;
case MemberTypes.Event:
temp = new SymbolInfoUnit(GetEvent(mi as EventInfo));
break;
default:
continue;
}
if (si == null)
si = new SymbolInfoList(temp);
else
si.Add(temp);
//temp.Next = si;
//si = temp;
}
}
Type nested_t = null;
foreach (Type nt in t.GetNestedTypes())
{
if (string.Compare(nt.Name, name, true) == 0)
{
nested_t = nt;
break;
}
}
if (nested_t != null)
{
SymbolInfoList temp = new SymbolInfoList(new SymbolInfoUnit(compiled_type_node.get_type_node(nested_t)));
temp.Add(si);
si = temp;
}
return si;
}
public static SymbolInfoUnit GetSymbolInfoForFieldNode(FieldInfo fi)
{
SymbolInfoUnit si = null;
if (fi.IsLiteral && !fi.FieldType.IsEnum)
{
compiled_class_constant_definition cd = GetConstantFieldNode(fi);
if (cd != null)
si = new SymbolInfoUnit(cd);
}
if (si == null)
si = new SymbolInfoUnit(GetFieldNode(fi));
return si;
}
/*
public static compiled_function_node GetMethodNode(MethodInfo mi)
{
compiled_function_node cfn = (compiled_function_node)meth_nodes[mi];
if (cfn != null) return cfn;
cfn = new compiled_function_node(mi);
meth_nodes[mi] = cfn;
return cfn;
}
*/
public static compiled_property_node GetPropertyNode(PropertyInfo pi)
{
compiled_property_node cpn = null;
if (prop_nodes.TryGetValue(pi, out cpn))
return cpn;
cpn = new compiled_property_node(pi);
prop_nodes[pi] = cpn;
return cpn;
}
public static compiled_variable_definition GetFieldNode(FieldInfo pi)
{
compiled_variable_definition cpn = field_nodes[pi] as compiled_variable_definition;
if (cpn != null)
{
if (cpn.type is compiled_type_node)
return cpn;
if (PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
if (cpn.type.type_special_kind == type_special_kind.typed_file &&
(!PascalABCCompiler.TreeConverter.compilation_context.instance.TypedFiles.ContainsKey(cpn.type.element_type) || PascalABCCompiler.TreeConverter.compilation_context.instance.TypedFiles[cpn.type.element_type] != cpn.type))
{
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(cpn.type.element_type,null);
return cpn;
}
else if (cpn.type.type_special_kind == type_special_kind.set_type &&
(!PascalABCCompiler.TreeConverter.compilation_context.instance.TypedSets.ContainsKey(cpn.type.element_type) || PascalABCCompiler.TreeConverter.compilation_context.instance.TypedSets[cpn.type.element_type] != cpn.type))
{
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(cpn.type.element_type,null);
return cpn;
}
else if (cpn.type.type_special_kind == type_special_kind.short_string &&
(!PascalABCCompiler.TreeConverter.compilation_context.instance.ShortStringTypes.ContainsKey((cpn.type as short_string_type_node).Length) || PascalABCCompiler.TreeConverter.compilation_context.instance.ShortStringTypes[(cpn.type as short_string_type_node).Length] != cpn.type))
{
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_short_string_type((cpn.type as short_string_type_node).Length,null);
return cpn;
}
}
}
cpn = new compiled_variable_definition(pi);
if (PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
object[] attrs = pi.GetCustomAttributes(false);
for (int i=0; i<attrs.Length; i++)
{
Type t = attrs[i].GetType();
if (t.FullName == compiler_string_consts.file_of_attr_name)
{
object o = t.GetField("Type",BindingFlags.Public|BindingFlags.Instance).GetValue(attrs[i]);
type_node tn = null;
if (o is Type)
t = o as Type;
else
{
t = t.Assembly.GetType(o as string,false);
tn = CreatePascalType(t);
}
if (tn != null)
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(tn,null);
else
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(compiled_type_node.get_type_node(t),null);
}
else if (t.FullName == compiler_string_consts.set_of_attr_name)
{
object o = t.GetField("Type",BindingFlags.Public|BindingFlags.Instance).GetValue(attrs[i]);
type_node tn = null;
if (o is Type)
t = o as Type;
else
{
t = t.Assembly.GetType(o as string,false);
tn = CreatePascalType(t);
}
if (tn != null)
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(tn,null);
else
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(compiled_type_node.get_type_node(t),null);
}
else if (t.FullName == compiler_string_consts.short_string_attr_name)
{
int len = (int)t.GetField("Length",BindingFlags.Public|BindingFlags.Instance).GetValue(attrs[i]);
cpn.type = PascalABCCompiler.TreeConverter.compilation_context.instance.create_short_string_type(len,null);
}
}
}
else
return cpn;
field_nodes[pi] = cpn;
return cpn;
}
private static constant_node CreateConstantNode(object value)
{
switch (Type.GetTypeCode(value.GetType()))
{
case TypeCode.Boolean:
return new TreeRealization.bool_const_node((Boolean)value, null);
case TypeCode.SByte:
return new TreeRealization.sbyte_const_node((SByte)value, null);
case TypeCode.Byte:
return new TreeRealization.byte_const_node((Byte)value, null);
case TypeCode.Char:
return new TreeRealization.char_const_node((Char)value, null);
case TypeCode.Int16:
return new TreeRealization.short_const_node((Int16)value, null);
case TypeCode.UInt16:
return new TreeRealization.ushort_const_node((UInt16)value, null);
case TypeCode.Int32:
return new TreeRealization.int_const_node((Int32)value, null);
case TypeCode.UInt32:
return new TreeRealization.uint_const_node((UInt32)value, null);
case TypeCode.Int64:
return new TreeRealization.long_const_node((Int64)value, null);
case TypeCode.UInt64:
return new TreeRealization.ulong_const_node((UInt64)value, null);
case TypeCode.Single:
return new TreeRealization.float_const_node((Single)value, null);
case TypeCode.Double:
return new TreeRealization.double_const_node((Double)value, null);
case TypeCode.String:
return new TreeRealization.string_const_node((String)value, null);
default:
return null;
}
}
public static compiled_class_constant_definition ConvertToConstant(compiled_variable_definition cvd)
{
if (cvd.compiled_field.IsLiteral && cvd.compiled_field.FieldType.IsEnum)
return new compiled_class_constant_definition(cvd.compiled_field, new enum_const_node((int)cvd.compiled_field.GetRawConstantValue(), cvd.type, null));
else
return null;
}
public static compiled_class_constant_definition GetConstantFieldNode(FieldInfo fi)
{
compiled_class_constant_definition cccd = field_nodes[fi] as compiled_class_constant_definition;
if (cccd != null) return cccd;
constant_node cn = CreateConstantNode(fi.GetRawConstantValue());
if (cn == null)
return null;
cccd = new compiled_class_constant_definition(fi, cn);
field_nodes[fi] = cccd;
return cccd;
}
public static field_access_level GetFieldAccessLevel(FieldInfo fi)
{
if (fi.IsPublic)
{
return SemanticTree.field_access_level.fal_public;
}
if (fi.IsPrivate)
{
return SemanticTree.field_access_level.fal_private;
}
return SemanticTree.field_access_level.fal_protected;
}
public static compiled_event GetEvent(EventInfo ei)
{
compiled_event ce = field_nodes[ei] as compiled_event;
if (ce != null)
{
return ce;
}
ce = new compiled_event(ei);
field_nodes[ei] = ce;
return ce;
}
public static System.Reflection.MethodInfo GetReadAccessor(PropertyInfo pi)
{
MethodInfo mi = pi.GetGetMethod(true);
if (mi != null && !mi.IsPrivate && !mi.IsAssembly)
return mi;
return null;
}
public static System.Reflection.MethodInfo GetWriteAccessor(PropertyInfo pi)
{
MethodInfo mi = pi.GetSetMethod(true);
if (mi != null && !mi.IsPrivate && !mi.IsAssembly)
return mi;
return null;
}
public static compiled_function_node get_compiled_method(compiled_type_node declaring_type, string method_name,
params compiled_type_node[] operands)
{
Type[] arr = new Type[operands.Length];
for (int i = 0; i < operands.Length; i++)
{
arr[i] = operands[i].compiled_type;
}
MethodInfo mi = declaring_type.compiled_type.GetMethod(method_name, arr);
compiled_function_node cfn = compiled_function_node.get_compiled_method(mi);
return cfn;
}
//Возвращает акцессор get, если есть. Иначе возвращает акцессор set, если есть. Иначе возвращает null.
public static System.Reflection.MethodInfo GetAnyAccessor(PropertyInfo pi)
{
MethodInfo get = pi.GetGetMethod(true);
MethodInfo set = pi.GetSetMethod(true);
if (get != null)
if(get.IsPrivate)
{
if (set != null && !set.IsPrivate)
return set;
else
return get;
}
else if (get.IsFamily)
{
if (set != null && set.IsPublic)
return set;
else
return get;
}
else if (get.IsAssembly)
{
if (set != null && (set.IsPublic||set.IsFamily))
return set;
else
return get;
}
else
return get;
//return pi.GetSetMethod(true);
return set;
}
public static compiled_constructor_node GetConstructorNode(ConstructorInfo ci)
{
return (compiled_constructor_node)constr_nodes[ci];
}
public static void AddConstructor(ConstructorInfo ci, compiled_constructor_node ccn)
{
constr_nodes[ci] = ccn;
}
public static Type FindType(string name)
{
FoundInfo fi = null;
if (type_search_cache.TryGetValue(name, out fi))
{
if (!fi.exists)
return null;
TypeInfo ti = fi.type_infos[0].type_info;
if (ti != null)
return ti.type;
}
TypeInfo t = (TypeInfo)types[name];
if (t != null)
{
fi = new FoundInfo(true, t);
type_search_cache[name] = fi;
return t.type;
}
else
{
fi = new FoundInfo(false);
type_search_cache[name] = fi;
}
return null;
}
public static Type FindRtlType(string name)
{
return PABCSystemType.Assembly.GetType(name, false, true);
}
public static template_class FindCompiledTemplateType(string name)
{
object o = compiled_pascal_types[name];
if (o != null)
{
template_class tc = o as template_class;
if (tc == null && PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
Type t = o as Type;
if (t != null)
{
tc = CreateTemplateClassType(t);
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = tc;
}
else
return null;
}
return tc;
}
return null;
}
public static type_node FindCompiledPascalType(string name)
{
object o = compiled_pascal_types[name];
if (o != null)
{
type_node tn = o as type_node;
if (tn == null && PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
Type t = o as Type;
if (t != null)
{
tn = CreatePascalType(t);
if (tn != null)
compiled_pascal_types[t.Namespace + "." + t.Name.Substring(1)] = tn;
else
return null;
}
else
return null;
}
else
{
if (PascalABCCompiler.TreeConverter.compilation_context.instance != null && PascalABCCompiler.TreeConverter.compilation_context.instance.syntax_tree_visitor.compiled_unit != null && PascalABCCompiler.TreeConverter.compilation_context.instance.converted_namespace != null)
{
if (tn.type_special_kind == type_special_kind.typed_file &&
(!PascalABCCompiler.TreeConverter.compilation_context.instance.TypedFiles.ContainsKey(tn.element_type) || PascalABCCompiler.TreeConverter.compilation_context.instance.TypedFiles[tn.element_type] != tn))
{
tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_typed_file_type(tn.element_type, null);
return tn;
}
else if (tn.type_special_kind == type_special_kind.set_type &&
(!PascalABCCompiler.TreeConverter.compilation_context.instance.TypedSets.ContainsKey(tn.element_type) || PascalABCCompiler.TreeConverter.compilation_context.instance.TypedSets[tn.element_type] != tn))
{
tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_set_type(tn.element_type, null);
return tn;
}
else if (tn.type_special_kind == type_special_kind.short_string &&
(!PascalABCCompiler.TreeConverter.compilation_context.instance.ShortStringTypes.ContainsKey((tn as short_string_type_node).Length) || PascalABCCompiler.TreeConverter.compilation_context.instance.ShortStringTypes[(tn as short_string_type_node).Length] != tn))
{
tn = PascalABCCompiler.TreeConverter.compilation_context.instance.create_short_string_type((tn as short_string_type_node).Length, null);
return tn;
}
}
return tn;
}
}
return null;
}
public static Type FindType(string name, PascalABCCompiler.TreeRealization.using_namespace_list _unar)
{
FoundInfo fi = null;
if (type_search_cache.TryGetValue(name, out fi))
{
if (!fi.exists)
return null;
TypeInfo ti = fi.GetTypeByNamespaceList(_unar);
if (ti != null)
if (cur_used_assemblies.ContainsKey(ti.type.Assembly))
return ti.type;
}
object o = types[name];
if (o == null)
{
type_search_cache[name] = new FoundInfo(false);
return null;
}
if (o is TypeInfo)
{
TypeInfo t = o as TypeInfo;
for (int i = 0; i < _unar.Count; i++)
{
if (string.Compare(_unar[i].namespace_name + "." + name, t.FullName, true) == 0)
{
if (!type_search_cache.TryGetValue(name, out fi))
{
fi = new FoundInfo(true, t, _unar[i]);
type_search_cache[name] = fi;
}
else
{
fi.type_infos.Add(new TypeNamespaceInfo(t, _unar[i]));
}
if (cur_used_assemblies.ContainsKey(t.type.Assembly))
return t.type;
else
return null;
}
}
return null;
}
else if (o is List<TypeInfo>)
{
foreach (TypeInfo t in o as List<TypeInfo>)
{
for (int i = 0; i < _unar.Count; i++)
{
if (string.Compare(_unar[i].namespace_name + "." + name, t.FullName, true) == 0)
{
if (!type_search_cache.TryGetValue(name, out fi))
{
fi = new FoundInfo(true, t, _unar[i]);
type_search_cache[name] = fi;
}
else
{
fi.type_infos.Add(new TypeNamespaceInfo(t, _unar[i]));
}
if (cur_used_assemblies.ContainsKey(t.type.Assembly))
return t.type;
else
return null;
}
}
}
return null;
}
for (int i = 0; i < _unar.Count; i++)
{
o = types[_unar[i].namespace_name + "." + name];
if (o == null)
continue;
if (o is TypeInfo)
return (o as TypeInfo).type;
List<TypeInfo> typs = o as List<TypeInfo>;
List<TypeInfo> founded_types = new List<TypeInfo>();
foreach (TypeInfo t in typs)
{
if (cur_used_assemblies.ContainsKey(t.type.Assembly))
founded_types.Add(t);
}
if (founded_types.Count == 1 && cur_used_assemblies.ContainsKey(founded_types[0].type.Assembly))
return founded_types[0].type;
else
return null;
}
return null;
}
public static void AddType(string name, Type t)
{
types[name] = new TypeInfo(t, t.FullName);
AddGenericInfo(t);
}
public static Type FindTypeOrCreate(string name)
{
TypeInfo ti = (TypeInfo)types[name];
if (ti != null /*&& cur_used_assemblies.ContainsKey(t.Assembly)*/) return ti.type;
//ivan added - runtime types adding
Type t = Type.GetType(name, false, true);
if (t == null)
foreach (Assembly a in assemblies.Values)
{
t = a.GetType(name, false, true);
if (t != null) break;
}
if (t != null)
{
types[name] = new TypeInfo(t, t.FullName);
AddGenericInfo(t);
}
return t;
}
public static Type FindAnyTypeInNamespace(string name)
{
foreach (string s in types.Keys)
{
TypeInfo ti = types[s] as TypeInfo;
if (string.Compare(ti.type.Namespace,name, true) == 0)
{
return ti.type;
}
}
return null;
}
private static void AddTypeToNamespace(string name, Type[] typs)
{
ns_types[name] = typs;
}
public static Type[] FindTypesInNamespace(string name)
{
List<Type> lst = new List<Type>();
Type[] typs = (Type[])ns_types[name];
if (typs != null) return typs;
foreach (string s in types.Keys)
{
TypeInfo ti = types[s] as TypeInfo;
if (ti != null)
if (string.Compare(ti.type.Namespace,name, true) == 0)
{
lst.Add(ti.type);
}
}
if (lst.Count == 0)
{
AddTypeToNamespace(name,new Type[0]);
return null;
}
typs = lst.ToArray();
AddTypeToNamespace(name,typs);
return typs;
}
public static string[] FindSubNamespaces(string name)
{
List<string> lst = new List<string>();
foreach (string s in namespaces.Keys)
{
if (s != name && s.StartsWith(name, StringComparison.CurrentCultureIgnoreCase))
lst.Add(s.Substring(name.Length+1));
}
if (lst == null) return null;
return lst.ToArray();
}
private static Hashtable InitHandles(Assembly a)
{
Type[] types = a.GetTypes();
Hashtable ht = new Hashtable();
foreach (Type t in types)
ht[(int)t.MetadataToken] = t;
type_handles[a] = ht;
return ht;
}
private static Hashtable InitMethodHandles(Type t)
{
MethodInfo[] mis = t.GetMethods();
Hashtable ht = new Hashtable();
foreach (MethodInfo mi in mis)
ht[(int)mi.MetadataToken] = mi;
method_handles[t] = ht;
return ht;
}
private static Hashtable InitConstructorHandles(Type t)
{
ConstructorInfo[] cis = t.GetConstructors();
Hashtable ht = new Hashtable();
foreach (ConstructorInfo ci in cis)
ht[(int)ci.MetadataToken] = ci;
constr_handles[t] = ht;
return ht;
}
private static Hashtable InitFieldHandles(Type t)
{
FieldInfo[] fis = t.GetFields();
Hashtable ht = new Hashtable();
foreach (FieldInfo fi in fis)
ht[(int)fi.MetadataToken] = fi;
field_handles[t] = ht;
return ht;
}
public static Type FindTypeByHandle(Assembly a, int handle)
{
Hashtable ht = (Hashtable)type_handles[a];
if (ht == null) ht = InitHandles(a);
Type t = (Type)ht[handle];
if (t == null)
return (Type)special_types[handle];
return t;
}
public static MethodInfo FindMethodByHandle(Type t, int handle)
{
Hashtable ht = (Hashtable)method_handles[t];
if (ht == null) ht = InitMethodHandles(t);
return (MethodInfo)ht[handle];
}
public static ConstructorInfo FindConstructorByHandle(Type t, int handle)
{
Hashtable ht = (Hashtable)constr_handles[t];
if (ht == null) ht = InitConstructorHandles(t);
return (ConstructorInfo)ht[handle];
}
public static FieldInfo FindFieldByHandle(Type t, int handle)
{
Hashtable ht = (Hashtable)field_handles[t];
if (ht == null) ht = InitFieldHandles(t);
return (FieldInfo)ht[handle];
}
public static void AddGenericInfo(Type t)
{
if (t == null || !t.IsGenericTypeDefinition)
return;
int n;
string s = compiler_string_consts.GetGenericTypeInformation(t.Name, out n).ToLower();
if (n == 0)
{
return;
}
List<int> counts;
bool exists = generics_names.TryGetValue(s, out counts);
if (!exists)
{
counts = new List<int>();
generics_names[s] = counts;
}
if (counts.IndexOf(n) < 0)
{
counts.Add(n);
}
}
public static constant_node make_constant(object val)
{
try
{
Type t = val.GetType();
if (t == typeof(int))
return new int_const_node((int)val, null);
if (t == typeof(byte))
return new byte_const_node((byte)val, null);
if (t == typeof(sbyte))
return new sbyte_const_node((sbyte)val, null);
if (t == typeof(short))
return new short_const_node((short)val, null);
if (t == typeof(ushort))
return new ushort_const_node((ushort)val, null);
if (t == typeof(uint))
return new uint_const_node((uint)val, null);
if (t == typeof(long))
return new long_const_node((long)val, null);
if (t == typeof(ulong))
return new ulong_const_node((ulong)val, null);
if (t == typeof(char))
return new char_const_node((char)val, null);
if (t == typeof(string))
return new string_const_node((string)val, null);
if (t == typeof(double))
return new double_const_node((double)val, null);
if (t == typeof(float))
return new double_const_node((float)val, null);
if (t.IsEnum)
return new enum_const_node(Convert.ToInt32(val), compiled_type_node.get_type_node(t), null);
}
catch
{
}
return null;
}
}
}