// 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 System.IO; using System.Collections; using System.Reflection; using TreeConverter; using PascalABCCompiler.TreeConverter; using PascalABCCompiler.TreeRealization; using System.Collections.Generic; namespace PascalABCCompiler.PCU { public class PCUConsts { public const byte template_meth = 250; public const byte template_field = 249; public const byte template_prop = 248; public const byte generic_meth = 240; public const byte generic_ctor = 239; public const byte generic_field = 238; public const byte generic_prop = 237; public const byte generic_param_ctor = 236; public const byte common_method_generic = 230; public const byte compiled_method_generic = 229; public const byte common_namespace_generic = 228; public const int method_instance_as_compiled_function_node = -1; } //класс, хранящий информацию об имени интерфейсной сущности и ее смещении в модуле public class NameRef { public string name;//имя сущности public TreeConverter.access_level access_level;//модификатор видимости public symbol_kind symbol_kind = symbol_kind.sk_none; public int offset;//смещение в модуле public byte special_scope=0;//говорит о том что этот символ добавляется не в пространсво имен модуля public int index;//не сериализуется public semantic_node_type semantic_node_type; public bool virtual_slot = false; public NameRef(string name, int index, TreeConverter.access_level access_level, semantic_node_type semantic_node_type) { this.name = name; this.index = index;//4 this.access_level = access_level;//1 this.semantic_node_type = semantic_node_type; } public NameRef(string name, int index) { this.name = name; this.index = index; this.access_level = TreeConverter.access_level.al_none; } public int Size { get { return (System.Text.UTF8Encoding.UTF8.GetByteCount(name) + 1) + 1 + 4 + 1 + 1 + 1 + 1; } } } public class ClassInfo { public int names_pos; public int def_prop_off; public int base_class_off; public int interf_impl_off; public NameRef[] names; public ClassInfo(int names_pos, int def_prop_off, int base_class_off, int interf_impl_off, NameRef[] names) { this.names_pos = names_pos; this.def_prop_off = def_prop_off; this.base_class_off = base_class_off; this.interf_impl_off = interf_impl_off; this.names = names; } } //вид импортируемой сущности public enum ImportKind { Common, DotNet } // public enum TypeKind { Array=2, Pointer=3, UnsizedArray=4, BoundedArray=5, TemplateInstance = 6, GenericInstance = 7, ShortString = 8, GenericParameterOfType = 9, GenericParameterOfFunction = 10, GenericParameterOfMethod = 11 } public enum GenericParamKind { None=0, Class=1, Value=2 } //класс, описывающий импортируемую сущность public class ImportedEntity { public ImportKind flag; //откуда импортируется сущность (сборка или PCU) public int num_unit;// public int offset;//для PCU - смещение в модуле, содержащем сущность, для .NET - MetadataToken сущности public int index;//индекс записи в списке импортируемых сущностей (не сериализуется) public int GetSize() { return 9; } public static int GetClassSize() { return 9; } } public enum DotNetKind { Field, Method, Constructor, Type, Property } public class DotAdditInfo { public int offset; } public class DotNetNameRef { public DotNetKind kind; public string name; public DotAdditInfo[] addit; } /// /// Класс, описывающий заголовок PCU-файла /// public class PCUFile { public static char[] Header = new char[3] { 'P', 'C', 'U'}; public static Int16 SupportedVersion = PCUFileFormatVersion.Version; public Int16 Version; public static int CRCOffset = 3 + 2; public Int64 CRC; public bool UseRtlDll; public bool IncludeDebugInfo; public string SourceFileName; public NameRef[] names; //список имен интерфейсной части модуля public string[] incl_modules; //список подключаемых модулей public string[] used_namespaces; public string[] ref_assemblies; //список подключаемых сборок public DotNetNameRef[] dotnet_names; //public AssemblyRef[] ref_assemblies; public ImportedEntity[] imp_entitles; //список импортируемых сущностей public List compiler_directives; //список директив //ssyy public NameRef[] implementation_names; public int interface_uses_count; //Количество модулей из incl_modules, относящихся к секции interface //public List interface_type_synonyms; //public List implementation_type_synonyms; public int interface_synonyms_offset; public int implementation_synonyms_offset; //public string[] implementation_incl_modules; //\ssyy public PCUFile() {} } /// /// Класс, создающий PCU-модуль /// public class PCUWriter { private BinaryWriter bw; private MemoryStream ms; private string name;//имя модуля public string FileName;//имя файла модуля private PCUFile pcu_file = new PCUFile(); //заголовок PCU private CompilationUnit unit; private common_unit_node cun; //текущий сериализуемый unit private Dictionary members = new Dictionary(); //таблица для хранения смещений сущностей модуля private Dictionary name_pool = new Dictionary();//таблица для связывания имени сущности с ее описанием //ssyy private Dictionary impl_name_pool = new Dictionary();//то же для implementation - части //\ssyy private List imp_entitles = new List();//список импортируемых сущностей, заполняется в процессе private List ref_assemblies = new List();//список подключаемых сборок, заполняется в процессе private Dictionary assm_refs = new Dictionary();//таблица для привязывания сборки private Dictionary func_codes = new Dictionary();//таблица, хранящая смещения тел методов в PCU private Dictionary used_units = new Dictionary(); private Dictionary ext_members = new Dictionary();//таблица, привязывающая импорт. сущность с записью в списке имп. сущ-тей private common_namespace_node cur_cnn;//текущее пространство имен private bool is_interface = true;//переводим ли интерфейсную часть //глобальная таблица для хранения смещений сущностей private static Dictionary gl_members = new Dictionary(); private Dictionary function_references = new Dictionary(); private Dictionary type_references = new Dictionary(); //глобальная таблица, привязывающая импортируемую сущность, смещение которой пока неизвестно с PCUWriter private static Dictionary> not_comp_members = new Dictionary>(); private static void add_not_comp_members(definition_node dn, PCUWriter pw) { if (not_comp_members.ContainsKey(dn)) { not_comp_members[dn].Add(pw); } else { List l=new List(); l.Add(pw); not_comp_members.Add(dn, l); } } //локальная таблица, привязывающая импортируемую сущность с записью в таблице импортируемых сущностей private Dictionary ext_offsets = new Dictionary(); private PCUReader pcu_reader = null; //требуется, если например требуется перекомпилировать модули PCU с циклическими связями private Dictionary class_info = new Dictionary(); private int InitializationMethodOffset = 0; private int FinalizationMethodOffset = 0; internal static List AllWriters=new List(); private Compiler compiler; public delegate void ChangeStateDelegate(object Sender, PCUReaderWriterState State, object obj); public event ChangeStateDelegate ChangeState; //ivan private List dot_net_name_list = new List(); private Hashtable tokens = new Hashtable(); //ivan public PCUWriter(Compiler compiler, ChangeStateDelegate changeState) { ChangeState += changeState; this.compiler = compiler; AllWriters.Add(this); } public static void Clear() { gl_members.Clear(); not_comp_members.Clear(); foreach (PCUWriter pw in AllWriters) if (pw.ext_offsets.Count > 0) ;//ошибка? AllWriters.Clear(); } //процедура сохранения модуля на диск public void SaveSemanticTree(CompilationUnit Unit, string TargetFileName, bool IncludeDebugInfo) { pcu_file.IncludeDebugInfo = IncludeDebugInfo; pcu_file.UseRtlDll = compiler.CompilerOptions.UseDllForSystemUnits; unit = Unit; cun = (common_unit_node)unit.SemanticTree; this.FileName = TargetFileName; string program_folder=System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(TargetFileName)); name = System.IO.Path.GetFileName(TargetFileName); //name = name.Substring(0,name.LastIndexOf('.'))+".pcu"; //FileStream fs = new FileStream(name,FileMode.Create,FileAccess.ReadWrite); ChangeState(this, PCUReaderWriterState.BeginSaveTree, TargetFileName); pcu_file.compiler_directives = cun.compiler_directives; if (Path.GetDirectoryName(TargetFileName).ToLower() == Path.GetDirectoryName(Unit.SyntaxTree.file_name).ToLower()) pcu_file.SourceFileName = Path.GetFileName(Unit.SyntaxTree.file_name); else pcu_file.SourceFileName = Unit.SyntaxTree.file_name; ms = new MemoryStream(); bw = new BinaryWriter(ms); //if (Unit.InterfaceUsedUnits.Count > 0) Console.WriteLine("{0} {1}",name,Unit.InterfaceUsedUnits[0].namespaces[0].namespace_name); cur_cnn = cun.namespaces[0]; //(ssyy) формируем список нешаблонных классов cur_cnn.MakeNonTemplateTypesList(); GetUsedUnits();//заполняем список полключаемых модулей GetCountOfMembers();//заполняем список имен интерфейсных сущностей WriteUnit();//пишем имя interface_namespace cur_cnn = cun.namespaces[1]; //(ssyy) формируем список нешаблонных классов cur_cnn.MakeNonTemplateTypesList(); GetCountOfImplementationMembers();//(ssyy) заполняем список имен сущностей реализации WriteUnit();//пишем имя implementation_namespace SaveOffsetForAttribute(cun.namespaces[0]); bw.Write(0);//attributes; cur_cnn = cun.namespaces[0]; //bw.Write((byte)0); //bw.Write((byte)0); //ssyy VisitTemplateClasses();//сериализуем шаблонные классы //\ssyy VisitTypeDefinitions();//сериализуем описания типов интерфейсной части //ssyy pcu_file.interface_synonyms_offset = (int)bw.BaseStream.Position; VisitTypeSynonyms(); //\ssyy cur_cnn = cun.namespaces[1]; is_interface = false; //ssyy VisitLabelDeclarations(cur_cnn.labels); //сериализуем метки type_entity_index = 0; VisitTemplateClasses();//сериализуем шаблонные классы //\ssyy VisitTypeDefinitions();//сериализуем описания типов имплемент. части //ssyy pcu_file.implementation_synonyms_offset = (int)bw.BaseStream.Position; VisitTypeSynonyms(); //\ssyy cur_cnn = cun.namespaces[0]; is_interface = true; foreach (common_type_node ctn in cur_cnn.non_template_types) { VisitTypeMemberDefinition(ctn); } cur_cnn = cun.namespaces[1]; is_interface = false; foreach (common_type_node ctn in cur_cnn.non_template_types) { VisitTypeMemberDefinition(ctn); } cur_cnn = cun.namespaces[0]; is_interface = true; VisitConstantDefinitions();//сериализуем константы VisitVariableDefinitions();//сериализуем переменные VisitFunctionDefinitions();//сериализуем функции VisitRefTypeDefinitions(); VisitEventDefinitions(); cur_cnn = cun.namespaces[1]; is_interface = false; entity_index = 0; //имплементационная часть VisitConstantDefinitions(); VisitVariableDefinitions(); VisitFunctionDefinitions(); VisitRefTypeDefinitions(); VisitEventDefinitions(); cur_cnn = cun.namespaces[0]; //сериализуем тела функций foreach (common_namespace_function_node cnfn in cur_cnn.functions) { VisitFunctionImplementation(cnfn); } //сериализуем тела методов и конструкторов типа foreach (common_type_node ctn in cur_cnn.non_template_types) { VisitTypeImplementation(ctn); } cur_cnn = cun.namespaces[1]; //имплементационная часть foreach (common_namespace_function_node cnfn in cur_cnn.functions) VisitFunctionImplementation(cnfn); foreach (common_type_node ctn in cur_cnn.non_template_types) { VisitTypeImplementation(ctn); } WriteVariablePositions(); WriteConstantPositions(); AddAttributes(); WriteInitExpressions(); WriteFunctionReferences(); WriteTypeReferences(); //сохранение интерфейсной и имплементац. частей модуля if (ext_offsets.Count != 0) { List dnl = new List(ext_offsets.Keys); foreach (definition_node wdn in dnl) { if (wdn is wrapped_definition_node) AddOffsetForMembers(wdn, (wdn as wrapped_definition_node).offset); else if (wdn is wrapped_common_type_node) AddOffsetForMembers(wdn, (wdn as wrapped_common_type_node).offset); else if (PCUReader.AllReadOrWritedDefinitionNodesOffsets.ContainsKey(wdn)) AddOffsetForMembers(wdn, PCUReader.AllReadOrWritedDefinitionNodesOffsets[wdn]); } } } //запись шапки PCU на диск private void WritePCUHeader(BinaryWriter fbw) { pcu_file.ref_assemblies = new string[ref_assemblies.Count]; for (int i=0; i> attr_dict = new Dictionary>(); private void SaveOffsetForAttribute(definition_node dn) { if (!attr_dict.ContainsKey(dn)) { attr_dict[dn] = new List(); } attr_dict[dn].Add((int)bw.BaseStream.Position); } private void AddAttributes() { foreach (definition_node dn in attr_dict.Keys) { SaveAttributes(dn.attributes,attr_dict[dn]); } } private void WriteCRC32InHeader(byte[] buf, BinaryWriter bw) { /*Crc32 CRC32 = new Crc32(); CRC32.Update(buf); bw.Seek(PCUFile.CRCOffset, SeekOrigin.Begin); bw.Write(CRC32.Value);*/ bw.Write((Int64)0); } // запись PCU на диск internal void CloseWriter() { FileStream fs = new FileStream(FileName, FileMode.Create, FileAccess.ReadWrite); BinaryWriter fbw = new BinaryWriter(fs); WritePCUHeader(fbw); byte[] buf = new byte[bw.BaseStream.Length]; bw.Seek(0, SeekOrigin.Begin); bw.BaseStream.Read(buf, 0, buf.Length); fbw.Write(buf); WriteCRC32InHeader(buf, fbw); bw.Close(); ms.Close(); fbw.Close(); fs.Close(); if (pcu_reader != null) pcu_reader.OpenUnit(); ChangeState(this, PCUReaderWriterState.EndSaveTree, FileName); } internal void RemoveSelf() { AllWriters.Remove(this); } public void AddPCUToOpen(PCUReader pr) { pcu_reader = pr; } //сохранен ли PCU на диск public bool IsSaved() { return ext_offsets.Count == 0; } private Dictionary> exprs_cache = new Dictionary>(); private void SaveExpressionAndOffset(expression_node expr) { List lst = null; if (!exprs_cache.ContainsKey(expr)) { lst = new List(); exprs_cache[expr] = lst; } else lst = exprs_cache[expr]; lst.Add((int)bw.BaseStream.Position); //System.Diagnostics.Debug.WriteLine((int)bw.BaseStream.Position); } private void FixupExpressionPosition(expression_node expr) { List poses = exprs_cache[expr]; //System.Diagnostics.Debug.WriteLine(pos); foreach (int pos in poses) { int tmp = (int)bw.BaseStream.Position; bw.Seek(pos,SeekOrigin.Begin); bw.Write(tmp); bw.Seek(tmp,SeekOrigin.Begin); } } private void WriteInitExpressions() { foreach (expression_node expr in exprs_cache.Keys) { FixupExpressionPosition(expr); VisitExpression(expr); } } private void WriteFunctionReferences() { foreach (int off in function_references.Keys) { common_namespace_function_node cnfn = function_references[off]; int pos = (int)bw.BaseStream.Position; bw.Seek(off, SeekOrigin.Begin); WriteFunctionReference(cnfn); bw.Seek(pos, SeekOrigin.Begin); } } private void WriteTypeReferences() { foreach (int off in type_references.Keys) { common_type_node ctn = type_references[off]; int pos = (int)bw.BaseStream.Position; bw.Seek(off, SeekOrigin.Begin); WriteTypeReference(ctn); bw.Seek(pos, SeekOrigin.Begin); } } //получения индекса сборки в списке подключаемых сборок private int GetAssemblyToken(Assembly a) { int pos = 0; if (assm_refs.TryGetValue(a, out pos)) { return pos; } int num = ref_assemblies.Count; ref_assemblies.Add(a.FullName); assm_refs[a]=num; return num; } //получение смещения сущности в модуле private int GetMemberOffset(definition_node dn) { int off = members[dn]; return members[dn]; } //получения индекса в таблице интерфейсных имен private int GetNameIndex(definition_node dn) { return name_pool[dn].index; } private int GetUnitReference(namespace_node nn) { return members[nn]; } //получение смещения в другом модуле private int GetExternalOffset(definition_node dn) { int off = -1; if (!gl_members.TryGetValue(dn, out off)) { add_not_comp_members(dn, this); ext_offsets[dn] = imp_entitles.Count; } return off; } //сериализована ли сущность private bool IsDefined(definition_node dn) { return members.ContainsKey(dn); } //добавить внешнюю сущность public static void AddExternalMember(definition_node dn, int offset) { gl_members[dn] = offset; } private int entity_index=0; private int type_entity_index = 0; //сохранить смещение сущности в таблицах и в списке интерфейсных имен private int SavePositionAndConstPool(definition_node dn) { int pos = (int)bw.BaseStream.Position; members[dn] = pos; name_pool[dn].offset = pos; if (dn is common_namespace_function_node) if ((dn as common_namespace_function_node).is_overload) name_pool[dn].symbol_kind = symbol_kind.sk_overload_function; gl_members[dn] = pos; List pwl = null; //если какой-то модуль ждет смещения от этой сущности, сообщаем ему if (not_comp_members.TryGetValue(dn, out pwl)) foreach(PCUWriter pw in pwl) pw.AddOffsetForMembers(dn, pos); PCUReader.AddReadOrWritedDefinitionNode(dn, pos); return pos; } //то же самое, но только для членов класса (это лишнее можно объединить) /* private int SavePositionAndConstPoolInType(definition_node dn) { int pos = (int)bw.BaseStream.Position; members[dn] = pos; name_pool[dn].offset = pos; gl_members[dn] = pos; PCUWriter pw = null; if (not_comp_members.TryGetValue(dn,out pw)) pw.AddOffsetForMembers(dn,pos); return pos; }*/ //просто сохраняем смещение сущности private int SavePosition(definition_node dn) { int pos = (int)bw.BaseStream.Position; members[dn] = pos; gl_members[dn] = pos; return pos; } //(ssyy) сохраняем смещение сущности (для implementation) private int SavePositionAndImplementationPool(definition_node dn) { int pos = (int)bw.BaseStream.Position; members[dn] = pos; impl_name_pool[dn].offset = pos; gl_members[dn] = pos; return pos; } //связываем сущность со смещением, по которому находится тело методов private void SaveCodeReference(function_node fn) { func_codes[fn] = (int)bw.BaseStream.Position; } //сообщаем функции смещение, по которому расположен ее код private void FixupCode(function_node fn) { int tmp = (int)bw.BaseStream.Position; int pos = func_codes[fn]; bw.Seek(pos,SeekOrigin.Begin); bw.Write(tmp); bw.Seek(tmp,SeekOrigin.Begin); } //заполнение списка интерфейсных имен модуля private void GetCountOfMembers() { int num = cur_cnn.constants.Count + cur_cnn.functions.Count + cur_cnn.non_template_types.Count + cur_cnn.runtime_types.Count + cur_cnn.variables.Count + cur_cnn.templates.Count + cur_cnn.ref_types.Count + cur_cnn.events.Count; pcu_file.names = new NameRef[num]; FillNames(pcu_file.names, name_pool); } //ssyy private void GetCountOfImplementationMembers() { int num = cur_cnn.constants.Count + cur_cnn.functions.Count + cur_cnn.non_template_types.Count + cur_cnn.runtime_types.Count + cur_cnn.variables.Count + cur_cnn.templates.Count + cur_cnn.ref_types.Count + cur_cnn.events.Count; pcu_file.implementation_names = new NameRef[num]; FillNames(pcu_file.implementation_names, impl_name_pool); } //\ssyy private string GetSynonimName(common_namespace_node cnn, compiled_type_node ctn) { for (int i = 0; i < cnn.type_synonyms.Count; i++) { if (cnn.type_synonyms[i].original_type == ctn) return cnn.type_synonyms[i].name; } return ctn.name; } //ssyy private void FillNames(NameRef[] name_array, Dictionary pools) { int j = 0, i = 0; for (i = j; i < cur_cnn.constants.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.constants[i - j].name, i); pools[cur_cnn.constants[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.templates.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.templates[i - j].name, i); pools[cur_cnn.templates[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.functions.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.functions[i - j].name, i); if (cur_cnn.functions[i - j].ConnectedToType != null) { name_array[i].special_scope = 1; if (cur_cnn.functions[i - j].return_value_type != null) name_array[i].symbol_kind = symbol_kind.sk_overload_function; else name_array[i].symbol_kind = symbol_kind.sk_overload_procedure; } pools[cur_cnn.functions[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.non_template_types.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.non_template_types[i - j].name, i); pools[cur_cnn.non_template_types[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.runtime_types.Count + j; i++) { name_array[i] = new NameRef(GetSynonimName(cur_cnn,cur_cnn.runtime_types[i - j]), i); //name_array[i] = new NameRef(cur_cnn.runtime_types[i - j].name, i); pools[cur_cnn.runtime_types[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.ref_types.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.ref_types[i - j].name, i); pools[cur_cnn.ref_types[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.variables.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.variables[i - j].name, i); pools[cur_cnn.variables[i - j]] = name_array[i]; } j = i; for (i = j; i < cur_cnn.events.Count + j; i++) { name_array[i] = new NameRef(cur_cnn.events[i - j].name, i); pools[cur_cnn.events[i - j]] = name_array[i]; } } //\ssyy //заполнение списка подключаемых модулей private void GetUsedUnits() { int num = 0; common_unit_node unt = null; for (int j = 0; j < unit.InterfaceUsedUnits.Count; j++) { unt = unit.InterfaceUsedUnits[j] as common_unit_node; if (unt == null) continue; if (unt.namespaces.Count != 0) num += 1;//unt.namespaces.Count; } for (int j = 0; j < unit.ImplementationUsedUnits.Count; j++) { unt = unit.ImplementationUsedUnits[j] as common_unit_node; if (unt == null) continue; if (unt.namespaces.Count != 0) num += 1;//unt.namespaces.Count; } pcu_file.incl_modules = new string[num]; int i = 0; num = 0; for (i=0; i 1) { pcu_file.incl_modules[num] = unt.namespaces[1].namespace_name; used_units[unt.namespaces[1]] = num; num++; }*/ } } //(ssyy) Запомнили, какие модули относятся к секции interface pcu_file.interface_uses_count = num; for (int j=0; j 1) { pcu_file.incl_modules[num] = unt.namespaces[1].namespace_name; used_units[unt.namespaces[1]] = num; num++; }*/ } } pcu_file.used_namespaces = cun.used_namespaces.ToArray(); } //получения индекса модуля в списке подключ. модулей private int GetUnitToken(common_namespace_node ns) { int tok = 0; if (!used_units.TryGetValue(ns,out tok)) { return used_units[(ns.cont_unit as common_unit_node).namespaces[0]]; } return tok; } private int GetTokenForNetEntity(FieldInfo val) { int off=0; object o = tokens[val]; if (o != null) return (int)o; DotNetNameRef dnnr = new DotNetNameRef(); dnnr.kind = DotNetKind.Field; dnnr.name = val.Name; dnnr.addit = new DotAdditInfo[0]; off = dot_net_name_list.Count; tokens.Add(val, dot_net_name_list.Count); dot_net_name_list.Add(dnnr); return off; } private int GetTokenForNetEntity(MethodInfo val) { int off = 0; //if (tokens.TryGetValue(val, out off)) return off; object o = tokens[val]; if (o != null) return (int)o; DotNetNameRef dnnr = new DotNetNameRef(); dnnr.kind = DotNetKind.Method; dnnr.name = val.Name; //if (val.GetParameters() != null) //{ ParameterInfo[] prms = val.GetParameters(); if (prms != null) { if (val.Name != "op_Explicit") dnnr.addit = new DotAdditInfo[prms.Length]; else dnnr.addit = new DotAdditInfo[prms.Length+1]; for (int i = 0; i < prms.Length; i++) { dnnr.addit[i] = new DotAdditInfo(); dnnr.addit[i].offset = GetTokenForNetEntity(prms[i].ParameterType); } if (val.Name == "op_Explicit") { dnnr.addit[prms.Length] = new DotAdditInfo(); dnnr.addit[prms.Length].offset = GetTokenForNetEntity(val.ReturnType); } } else dnnr.addit = new DotAdditInfo[0]; //} off = dot_net_name_list.Count; tokens.Add(val, dot_net_name_list.Count); dot_net_name_list.Add(dnnr); return off; } private int GetTokenForNetEntity(ConstructorInfo val) { int off = 0; //if (tokens.TryGetValue(val, out off)) return off; object o = tokens[val]; if (o != null) return (int)o; DotNetNameRef dnnr = new DotNetNameRef(); dnnr.kind = DotNetKind.Constructor; dnnr.name = ".ctor"; //if (val.GetParameters() != null) //{ ParameterInfo[] prms = val.GetParameters(); if (prms != null) { dnnr.addit = new DotAdditInfo[prms.Length]; for (int i = 0; i < prms.Length; i++) { dnnr.addit[i] = new DotAdditInfo(); dnnr.addit[i].offset = GetTokenForNetEntity(prms[i].ParameterType); } } else dnnr.addit = new DotAdditInfo[0]; //} off = dot_net_name_list.Count; tokens.Add(val, dot_net_name_list.Count); dot_net_name_list.Add(dnnr); return off; } private int GetTokenForNetEntity(PropertyInfo val) { int off = 0; //if (tokens.TryGetValue(val, out off)) return off; object o = tokens[val]; if (o != null) return (int)o; DotNetNameRef dnnr = new DotNetNameRef(); dnnr.kind = DotNetKind.Property; dnnr.name = val.Name; //if (val.GetParameters() != null) //{ /*ParameterInfo[] prms = val.GetIndexParameters(); if (prms != null) { dnnr.addit = new DotAdditInfo[prms.Length]; for (int i = 0; i < prms.Length; i++) { dnnr.addit[i] = new DotAdditInfo(); dnnr.addit[i].offset = GetTokenForNetEntity(prms[i].ParameterType); } } else*/ dnnr.addit = new DotAdditInfo[0]; //} off = dot_net_name_list.Count; tokens.Add(val, dot_net_name_list.Count); dot_net_name_list.Add(dnnr); return off; } private int GetTokenForNetEntity(Type val) { int off = 0; //if (tokens.TryGetValue(val, out off)) return off; object o = tokens[val]; if (o != null) return (int)o; DotNetNameRef dnnr = new DotNetNameRef(); dnnr.kind = DotNetKind.Type; if (val.FullName != null) { //(ssyy) для инстанций generic-ов пишем имя оригинала if (val.IsGenericType && !val.IsGenericTypeDefinition) dnnr.name = val.GetGenericTypeDefinition().FullName; else dnnr.name = val.FullName; } else if (val.IsGenericType && !val.IsGenericTypeDefinition) dnnr.name = val.GetGenericTypeDefinition().FullName; else dnnr.name = val.Name; // if (val.IsGenericType) //{ Type[] tt = (val.IsGenericTypeDefinition)? new Type[0] : val.GetGenericArguments(); dnnr.addit = new DotAdditInfo[tt.Length]; for (int i = 0; i < tt.Length; i++) { dnnr.addit[i] = new DotAdditInfo(); dnnr.addit[i].offset = GetTokenForNetEntity(tt[i]); } //} off = dot_net_name_list.Count; tokens.Add(val, dot_net_name_list.Count); dot_net_name_list.Add(dnnr); return off; } //получения ссылки на тип private int GetTypeReference(type_node tn, ref byte is_def) { //если это откомпилир. тип if (tn.semantic_node_type == semantic_node_type.compiled_type_node) { is_def = 0; compiled_type_node ctn = (compiled_type_node)tn; ImportedEntity ie = null; if (ext_members.TryGetValue(ctn,out ie)) { return ie.index*ie.GetSize(); } //заполняем структуру в списке импортируемых сущностей ie = new ImportedEntity(); ie.index = imp_entitles.Count; ie.flag = ImportKind.DotNet; ie.num_unit = GetAssemblyToken(ctn.compiled_type.Assembly); //ie.offset = (int)ctn.compiled_type.MetadataToken;//токен для типа (уникален в сборке) ie.offset = GetTokenForNetEntity(ctn.compiled_type); int offset = imp_entitles.Count*ie.GetSize(); imp_entitles.Add(ie);//добавляем структуру ext_members[ctn] = ie; return offset;//возвращаем смещение относительно начала списка импорт. сущ-тей } else { int off = 0; if (members.TryGetValue(tn, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } //иначе он описан в другом модуле is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(tn, out ie)) { return ie.index * ie.GetSize(); } common_type_node ctn = (common_type_node)tn; ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetUnitToken(ctn.comprehensive_namespace);//получаем модуль ie.offset = GetExternalOffset(ctn);//получаем смещение в другом модуле int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[ctn] = ie; return offset; } } //ssyy private int GetTemplateTypeReference(template_class tc, ref byte is_def) { int off = 0; if (members.TryGetValue(tc, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } //иначе он описан в другом модуле is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(tc, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetUnitToken(tc.cnn);//получаем модуль ie.offset = GetExternalOffset(tc);//получаем смещение в другом модуле int offset = imp_entitles.Count * ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[tc] = ie; return offset; } //\ssyy //получения ссылки на откомпилированный тип private int GetCompiledTypeReference(compiled_type_node ctn) { ImportedEntity ie = null; if (ext_members.TryGetValue(ctn, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.index = imp_entitles.Count; ie.flag = ImportKind.DotNet; ie.num_unit = GetAssemblyToken(ctn.compiled_type.Assembly); //ie.offset = (int)ctn.compiled_type.MetadataToken; ie.offset = GetTokenForNetEntity(ctn.compiled_type); int offset = imp_entitles.Count*ie.GetSize(); imp_entitles.Add(ie); ext_members[ctn] = ie; return offset; } //получение ссылки на тип, описанный в другом модуле private int GetExtTypeReference(common_type_node ctn) { ImportedEntity ie = null; if (ext_members.TryGetValue(ctn, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetUnitToken(ctn.comprehensive_namespace); ie.offset = GetExternalOffset(ctn); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[ctn] = ie; return offset; } //запись ссылки на тип //флаг|смещение private void WriteTypeReference(type_node type) { if (type == null) { bw.Write((System.Byte)255); return; } //если это массив if (type.semantic_node_type == semantic_node_type.simple_array) { WriteArrayType((simple_array)type); return; } //если это указатель //Наверно также надо сохранять Pointer, // пока он востанавливается из таблицы nethelper.special_types if (type.semantic_node_type == semantic_node_type.ref_type_node) { WritePointerType((ref_type_node)type); return; } if (type.semantic_node_type == semantic_node_type.short_string) { WriteShortStringType((short_string_type_node)type); return; } internal_interface ii=type.get_internal_interface(internal_interface_kind.unsized_array_interface); //(ssyy) 18.05.2008 Убрал проверку на compiled_type_node if (ii != null) //&& type.element_type is compiled_type_node) { array_internal_interface aii=(array_internal_interface)ii; WriteUnsizedArrayType(type,aii); return; } //Пишем параметр generic-типа if (type.is_generic_parameter) { WriteGenericParameter(type as common_type_node); return; } //Пишем инстанцию generic-типа generic_instance_type_node gitn = type as generic_instance_type_node; if (gitn != null) { WriteGenericTypeInstance(gitn); return; } //Пишем инстанцию шаблонного класса common_type_node c_t_n = type as common_type_node; if (c_t_n != null && c_t_n.original_template != null) { WriteTemplateInstance(c_t_n); return; } byte is_def = 0; int offset = GetTypeReference(type, ref is_def); bw.Write(is_def); //пишем флаг импортируемый ли это тип или нет bw.Write(offset); // сохраняем его смещение (это либо смещение в самом модуле, либо в списке импорт. сущностей) } private void WriteTypeReferenceWithDelay(common_type_node type) { type_references.Add((int)bw.BaseStream.Position, type); bw.Write((byte)0); bw.Write(0); } private void WriteTypeList(List types) { bw.Write(types.Count); foreach (type_node t_n in types) { WriteTypeReference(t_n); } } //(ssyy) Сохранение инстанции шаблонного класса private void WriteTemplateInstance(common_type_node cnode) { bw.Write((byte)TypeKind.TemplateInstance); //Записать ссылку на шаблонный класс WriteTemplateClassReference(cnode.original_template); WriteTypeList(cnode.original_template.GetParamsList(cnode)); } //(ssyy) Сохранение инстанции generic-класса private void WriteGenericTypeInstance(generic_instance_type_node gitn) { bw.Write((byte)TypeKind.GenericInstance); //Пишем ссылку на описание generic-типа WriteTypeReference(gitn.original_generic); WriteTypeList(gitn.instance_params); } private void WriteGenericNamespaceFunctionReference(generic_namespace_function_instance_node func) { bw.Write((byte)PCUConsts.common_namespace_generic); WriteFunctionReference(func.original_function as common_namespace_function_node); WriteTypeList(func.instance_params); } private void WriteGenericMethodReference(function_node meth) { common_method_node cnode = meth.original_function as common_method_node; if (cnode != null) { bw.Write((byte)PCUConsts.common_method_generic); WriteMethodReference(cnode); } else { compiled_function_node comp = meth.original_function as compiled_function_node; bw.Write((byte)PCUConsts.compiled_method_generic); WriteCompiledMethod(comp); } WriteTypeList(meth.get_generic_params_list()); } //(ssyy) Сохранение параметров generic-типов private void WriteGenericParameter(common_type_node type) { if (type.generic_type_container != null) { bw.Write((byte)TypeKind.GenericParameterOfType); //Пишем ссылку на generic-тип, содержащий данный параметр if (type.generic_type_container is common_type_node) WriteTypeReferenceWithDelay(type.generic_type_container as common_type_node); else WriteTypeReference(type.generic_type_container as type_node); } else { common_method_node cnode = type.generic_function_container as common_method_node; if (cnode != null) { bw.Write((byte)TypeKind.GenericParameterOfMethod); WriteMethodReference(cnode); } else { common_namespace_function_node cnfn = type.generic_function_container as common_namespace_function_node; bw.Write((byte)TypeKind.GenericParameterOfFunction); WriteFunctionReferenceWithDelay(cnfn); } } bw.Write(type.generic_param_index); } //сохранение типа-массив private void WriteArrayType(simple_array type) { int offset = (int)bw.BaseStream.Position; bw.Write((byte)TypeKind.Array); WriteTypeReference(type.element_type); bw.Write(type.length); members[type] = offset;//это для нашего модуля //ext_members[type] = offset;//это для других модулей //VisitPropertyDefinition(type.default_property_node, offset); } //сохранение типа-указатель private void WritePointerType(ref_type_node type) { bw.Write((byte)TypeKind.Pointer); WriteTypeReference(type.pointed_type); } private void WriteShortStringType(short_string_type_node type) { bw.Write((byte)TypeKind.ShortString); bw.Write(type.Length); } private void WriteBoundedArray(bounded_array_interface bai) { bw.Write((byte)TypeKind.BoundedArray); VisitExpression(bai.ordinal_type_interface.lower_value); VisitExpression(bai.ordinal_type_interface.upper_value); WriteTypeReference(bai.element_type); } private void WriteUnsizedArrayType(type_node type,array_internal_interface aii) { bw.Write((byte)TypeKind.UnsizedArray); WriteDebugInfo((type as SemanticTree.ILocated).Location); WriteTypeReference(aii.element_type); bw.Write(aii.rank); } //получение ссылки на функцию private int GetFunctionReference(common_namespace_function_node fn, ref byte is_def) { int off = 0; if (members.TryGetValue(fn, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(fn, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetUnitToken(fn.namespace_node); ie.offset = GetExternalOffset(fn); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[fn] = ie; return offset; } //получение ссылки на откомпилированный метод private int GetCompiledMethod(compiled_function_node cfn) { ImportedEntity ie = null; if (ext_members.TryGetValue(cfn, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.DotNet; ie.num_unit = GetCompiledTypeReference(cfn.cont_type); //ie.offset = (int)cfn.method_info.MetadataToken; ie.offset = GetTokenForNetEntity(cfn.method_info); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[cfn] = ie; return offset; } //получение ссылки на откомпилированный конструктор private int GetCompiledConstructor(compiled_constructor_node ccn) { ImportedEntity ie = null; if (ext_members.TryGetValue(ccn, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.DotNet; ie.num_unit = GetCompiledTypeReference(ccn.compiled_type); //ie.offset = (int)ccn.constructor_info.MetadataToken; ie.offset = GetTokenForNetEntity(ccn.constructor_info); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[ccn] = ie; return offset; } //получение ссылки на откомпилированное свойство private int GetCompiledProperty(compiled_property_node cpn) { ImportedEntity ie = null; if (ext_members.TryGetValue(cpn, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.DotNet; ie.num_unit = GetCompiledTypeReference(cpn.compiled_comprehensive_type); //ie.offset = (int)ccn.constructor_info.MetadataToken; ie.offset = GetTokenForNetEntity(cpn.property_info); int offset = imp_entitles.Count * ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[cpn] = ie; return offset; } private void WriteFunctionReferenceWithDelay(common_namespace_function_node fn) { function_references.Add((int)bw.BaseStream.Position, fn); bw.Write((byte)0); bw.Write(0); } //сохранение ссылки на функцию private void WriteFunctionReference(common_namespace_function_node fn) { generic_namespace_function_instance_node gi = fn as generic_namespace_function_instance_node; if (gi != null) { WriteGenericNamespaceFunctionReference(gi); return; } byte is_def = 0; int offset=0; if (fn.SpecialFunctionKind == SemanticTree.SpecialFunctionKind.None) offset = GetFunctionReference(fn, ref is_def); else is_def = 2; bw.Write(is_def); if (fn.SpecialFunctionKind == SemanticTree.SpecialFunctionKind.None) bw.Write(offset); else bw.Write((byte)fn.SpecialFunctionKind); } //сохранение ссылки на откомпилированный метод private void WriteCompiledMethod(compiled_function_node cfn) { if (cfn.is_generic_function_instance) { bw.Write(PCUConsts.method_instance_as_compiled_function_node); WriteGenericMethodReference(cfn); return; } bw.Write(GetCompiledMethod(cfn)); } private void WriteCompiledConstructor(compiled_constructor_node ccn) { bw.Write(GetCompiledConstructor(ccn)); } private void WriteCompiledProperty(compiled_property_node cpn) { bw.Write(GetCompiledProperty(cpn)); } private int GetVariableReference(namespace_variable nv, ref byte is_def) { int off = 0; if (members.TryGetValue(nv, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } if (!used_units.ContainsKey(nv.namespace_node)) { is_def = 1; return -1; } is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(nv, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetUnitToken(nv.namespace_node); ie.offset = GetExternalOffset(nv); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[nv] = ie; return offset; } private int GetConstantReference(namespace_constant_definition nv, ref byte is_def) { int off = 0; if (members.TryGetValue(nv, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } if (!used_units.ContainsKey(nv.comprehensive_namespace)) { is_def = 1; return -1; } is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(nv, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetUnitToken(nv.comprehensive_namespace); ie.offset = GetExternalOffset(nv); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[nv] = ie; return offset; } private int GetCompiledVariable(compiled_variable_definition cvd) { ImportedEntity ie = null; if (ext_members.TryGetValue(cvd, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.DotNet; ie.num_unit = GetCompiledTypeReference(cvd.cont_type); //ie.offset = (int)cvd.compiled_field.MetadataToken; ie.offset = GetTokenForNetEntity(cvd.compiled_field); ie.index = imp_entitles.Count; int offset = imp_entitles.Count*ie.GetSize(); imp_entitles.Add(ie); ext_members[cvd] = ie; return offset; } private Hashtable var_positions = new Hashtable(); private Hashtable const_positions = new Hashtable(); private void SaveVariableReferencePosition(namespace_variable nv) { List offs = (List)var_positions[nv]; if (offs == null) { offs = new List(); var_positions[nv] = offs; } offs.Add((int)bw.BaseStream.Position); } private void SaveConstantReferencePosition(namespace_constant_definition nv) { List offs = (List)const_positions[nv]; if (offs == null) { offs = new List(); const_positions[nv] = offs; } offs.Add((int)bw.BaseStream.Position); } private void WriteVariablePositions() { int tmp = (int)bw.BaseStream.Position; foreach (namespace_variable nv in var_positions.Keys) { List offs = (List)var_positions[nv]; byte is_def = 0; for (int i = 0; i < offs.Count; i++) { bw.Seek(offs[i], SeekOrigin.Begin); bw.Write(GetVariableReference(nv,ref is_def)); } } bw.BaseStream.Position = tmp; } private void WriteConstantPositions() { int tmp = (int)bw.BaseStream.Position; foreach (namespace_constant_definition nv in const_positions.Keys) { List offs = (List)const_positions[nv]; byte is_def = 0; for (int i = 0; i < offs.Count; i++) { bw.Seek(offs[i], SeekOrigin.Begin); bw.Write(GetConstantReference(nv,ref is_def)); } } bw.BaseStream.Position = tmp; } private void WriteVariableReference(namespace_variable nv) { byte is_def = 0; int offset = GetVariableReference(nv, ref is_def); bw.Write(is_def); if (offset == -1) SaveVariableReferencePosition(nv); bw.Write(offset); } private void WriteConstantReference(namespace_constant_definition nv) { byte is_def = 0; int offset = GetConstantReference(nv, ref is_def); bw.Write(is_def); if (offset == -1) SaveConstantReferencePosition(nv); bw.Write(offset); } private void WriteCompiledVariable(compiled_variable_definition cvd) { bw.Write(GetCompiledVariable(cvd)); } private int GetEventReference(event_node ev, ref byte is_def) { if (ev.semantic_node_type == semantic_node_type.compiled_event) { is_def = 2; compiled_event cev = (compiled_event)ev; ImportedEntity ie = null; if (ext_members.TryGetValue(cev, out ie)) { return ie.index * ie.GetSize(); } //заполняем структуру в списке импортируемых сущностей ie = new ImportedEntity(); ie.index = imp_entitles.Count; ie.flag = ImportKind.DotNet; ie.num_unit = GetAssemblyToken(cev.event_info.DeclaringType.Assembly); //ie.offset = (int)ctn.compiled_type.MetadataToken;//токен для типа (уникален в сборке) ie.offset = GetTokenForNetEntity(cev.event_info.DeclaringType); int offset = imp_entitles.Count * ie.GetSize(); imp_entitles.Add(ie);//добавляем структуру ext_members[cev] = ie; return offset;//возвращаем смещение относительно начала списка импорт. сущ-тей } else if (ev.semantic_node_type == semantic_node_type.common_namespace_event) { int off = 0; if (members.TryGetValue(ev, out off)) //если этот тип описан в этом модуле { is_def = 4; return off;//возвращаем его смещение } is_def = 3; ImportedEntity ie = null; if (ext_members.TryGetValue(ev, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetUnitReference((ev as common_namespace_event).namespace_node); ie.offset = GetExternalOffset(ev); int offset = imp_entitles.Count * ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[ev] = ie; return offset; } else { int off = 0; if (members.TryGetValue(ev, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(ev, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetExtTypeReference((ev as common_event).cont_type); ie.offset = GetExternalOffset(ev); int offset = imp_entitles.Count * ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[ev] = ie; return offset; } } private int GetFieldReference(class_field field, ref byte is_def) { int off = 0; if (members.TryGetValue(field, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(field, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetExtTypeReference(field.cont_type); ie.offset = GetExternalOffset(field); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[field] = ie; return offset; } private void WriteFieldReference(class_field field) { generic_instance_type_node gitn = field.cont_type as generic_instance_type_node; if (gitn != null) { bw.Write(PCUConsts.generic_field); WriteGenericTypeInstance(gitn); if (gitn is compiled_generic_instance_type_node) { WriteCompiledVariable( gitn.get_member_definition(field) as compiled_variable_definition ); } else { WriteFieldReference(gitn.get_member_definition(field) as class_field); } return; } common_type_node ctnode = field.comperehensive_type as common_type_node; if (ctnode != null && ctnode.original_template != null) { bw.Write(PCUConsts.template_field); //т.е. пишем на место is_def WriteTemplateInstance(ctnode); bw.Write(ctnode.fields.IndexOf(field)); return; } byte is_def = 0; int offset = GetFieldReference(field, ref is_def); bw.Write(is_def); bw.Write(offset); } private int GetMethodReference(common_method_node meth, ref byte is_def) { int off = 0; if (members.TryGetValue(meth, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(meth, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetExtTypeReference(meth.cont_type); ie.offset = GetExternalOffset(meth); int offset = imp_entitles.Count*ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[meth] = ie; return offset; } private void WriteEventReference(event_node ev) { byte is_def = 0; int offset = GetEventReference(ev, ref is_def); bw.Write(is_def); bw.Write(offset); } private void WriteMethodReference(common_method_node meth) { if (meth.comperehensive_type.is_generic_parameter) { bw.Write(PCUConsts.generic_param_ctor); WriteGenericParameter(meth.comperehensive_type as common_type_node); return; } generic_method_instance_node gmin = meth as generic_method_instance_node; if (gmin != null) { WriteGenericMethodReference(gmin); return; } generic_instance_type_node gitn = meth.comperehensive_type as generic_instance_type_node; if (gitn != null) { if (gitn is common_generic_instance_type_node) { bw.Write(PCUConsts.generic_meth); WriteGenericTypeInstance(gitn); WriteMethodReference(gitn.get_member_definition(meth) as common_method_node); return; } if (meth.is_constructor) { bw.Write(PCUConsts.generic_ctor); WriteGenericTypeInstance(gitn); WriteCompiledConstructor( gitn.get_member_definition(meth) as compiled_constructor_node ); return; } bw.Write(PCUConsts.generic_meth); WriteGenericTypeInstance(gitn); WriteCompiledMethod( gitn.get_member_definition(meth) as compiled_function_node ); return; } common_type_node ctnode = meth.comperehensive_type as common_type_node; if (ctnode != null && ctnode.original_template != null) { bw.Write(PCUConsts.template_meth); //т.е. пишем на место is_def WriteTemplateInstance(ctnode); bw.Write(ctnode.methods.IndexOf(meth)); return; } //generic_namespace_function_instance_node gnfin = meth as generic_namespace_function_instance_node; //if (gnfin != null) //{ // WriteGenericNamespaceFunctionReference(gnfin); // return; //} byte is_def = 0; int offset = GetMethodReference(meth, ref is_def); bw.Write(is_def); bw.Write(offset); } private void WriteTemplateClassReference(template_class tc) { byte is_def = 0; int t_offset = GetTemplateTypeReference(tc, ref is_def); bw.Write(is_def); //пишем флаг импортируемый ли это тип или нет bw.Write(t_offset); // сохраняем его смещение (это либо смещение в самом модуле, либо в списке импорт. сущностей) } private int GetPropertyReference(common_property_node prop, ref byte is_def) { int off = 0; if (members.TryGetValue(prop, out off)) //если этот тип описан в этом модуле { is_def = 1; return off;//возвращаем его смещение } is_def = 0; ImportedEntity ie = null; if (ext_members.TryGetValue(prop, out ie)) { return ie.index * ie.GetSize(); } ie = new ImportedEntity(); ie.flag = ImportKind.Common; ie.num_unit = GetExtTypeReference(prop.common_comprehensive_type); ie.offset = GetExternalOffset(prop); int offset = imp_entitles.Count * ie.GetSize(); ie.index = imp_entitles.Count; imp_entitles.Add(ie); ext_members[prop] = ie; return offset; } private void WriteMethodReference(function_node fn) { if (fn is common_method_node) { bw.Write((byte)0); WriteMethodReference(fn as common_method_node); } else if (fn is compiled_constructor_node) { bw.Write((byte)1); bw.Write(GetCompiledConstructor(fn as compiled_constructor_node)); } else if (fn is compiled_function_node) { bw.Write((byte)2); bw.Write(GetCompiledMethod(fn as compiled_function_node)); } } private void WritePropertyReference(property_node pn) { if (pn is common_property_node) { bw.Write((byte)0); WritePropertyReference(pn as common_property_node); } else if (pn is compiled_property_node) { bw.Write((byte)1); bw.Write(GetCompiledProperty(pn as compiled_property_node)); } } private void WriteFieldReference(var_definition_node vdn) { if (vdn is class_field) { bw.Write((byte)0); WriteFieldReference(vdn as class_field); } else if (vdn is compiled_variable_definition) { bw.Write((byte)1); bw.Write(GetCompiledVariable(vdn as compiled_variable_definition)); } } private void WritePropertyReference(common_property_node prop) { //ssyy generic_instance_type_node gitn = prop.common_comprehensive_type as generic_instance_type_node; if (gitn != null) { bw.Write(PCUConsts.generic_prop); WriteGenericTypeInstance(gitn); if (gitn is compiled_generic_instance_type_node) { WriteCompiledProperty( gitn.get_member_definition(prop) as compiled_property_node ); } else { WritePropertyReference(gitn.get_member_definition(prop) as common_property_node); } return; } common_type_node ctnode = prop.common_comprehensive_type as common_type_node; if (ctnode != null && ctnode.original_template != null) { bw.Write(PCUConsts.template_prop); //т.е. пишем на место is_def WriteTemplateInstance(ctnode); bw.Write(ctnode.properties.IndexOf(prop)); return; } //\ssyy byte is_def = 0; int offset = GetPropertyReference(prop, ref is_def); bw.Write(is_def); bw.Write(offset); } //сохранение пространства имен private void WriteUnit() { SavePosition(cur_cnn); bw.Write(cur_cnn.namespace_name); WriteDebugInfo(cur_cnn.Location); } //сохранение констант private void VisitConstantDefinitions() { bw.Write(cur_cnn.constants.Count); for (int i = 0; i < cur_cnn.constants.Count; i++) VisitConstantDefinition(cur_cnn.constants[i]); } //сохранение указателей на тип private void VisitRefTypeDefinitions() { bw.Write(cur_cnn.ref_types.Count); for (int i = 0; i < cur_cnn.ref_types.Count; i++) VisitRefTypeDefinition(cur_cnn.ref_types[i]); } private void VisitRefTypeDefinition(ref_type_node node) { if (is_interface == true) SavePositionAndConstPool(node); else SavePositionAndImplementationPool(node); bw.Write((byte)node.semantic_node_type); bw.Write(is_interface); if (is_interface == true) bw.Write(GetNameIndex(node)); else bw.Write(node.name); //bw.Write(GetUnitReference(node.comprehensive_namespace)); WriteTypeReference(node.pointed_type); WriteDebugInfo(node.loc); } //сохранение константы private void VisitConstantDefinition(namespace_constant_definition cnst) { if (is_interface == true) SavePositionAndConstPool(cnst); else SavePositionAndImplementationPool(cnst); bw.Write((byte)cnst.semantic_node_type); bw.Write(is_interface); if (is_interface == true) bw.Write(GetNameIndex(cnst)); else bw.Write(cnst.name); bw.Write(GetUnitReference(cnst.comprehensive_namespace)); SaveExpressionAndOffset(cnst.const_value); bw.Write(0); //VisitExpression(cnst.const_value); WriteDebugInfo(cnst.loc); } //сохранение переменных модуля private void VisitVariableDefinitions() { bw.Write(cur_cnn.variables.Count); for (int i=0; i labels) { bw.Write(labels.Count); foreach (label_node ln in labels) { VisitLabelDeclaration(ln); } } //сохранение шаблонных классов private void VisitTemplateClasses() { bw.Write(cur_cnn.templates.Count); for (int i = 0; i < cur_cnn.templates.Count; i++) VisitTemplateClassDefinition(cur_cnn.templates[i]); } //сохранение синонимов типов private void VisitTypeSynonyms() { bw.Write(cur_cnn.type_synonyms.Count); for (int i = 0; i < cur_cnn.type_synonyms.Count; i++) VisitTypeSynonym(cur_cnn.type_synonyms[i]); } private void SaveAttributes(attributes_list attrs, List offs) { int tmp = (int)bw.BaseStream.Position; for (int i=0; i tpars) { foreach (common_type_node par in tpars) { //class - value if (par.is_class) { bw.Write((byte)GenericParamKind.Class); } else { if (par.is_value) { bw.Write((byte)GenericParamKind.Value); } else { bw.Write((byte)GenericParamKind.None); } } //предок WriteTypeReference(par.base_type); //интерфейсы WriteImplementingInterfaces(par); //конструктор по умолчанию if (par.methods.Count > 0) { bw.Write((byte)1); } else { bw.Write((byte)0); } //if (CanWriteObject(par.runtime_initialization_marker)) //{ // WriteFieldReference(par.runtime_initialization_marker); //} } } private int GetSizeOfReference(type_node tn) { if (tn == null) return sizeof(byte); if (tn.is_generic_parameter) { return sizeof(byte) + GetSizeOfReference(tn.generic_type_container as type_node) + sizeof(int); } generic_instance_type_node gitn = tn as generic_instance_type_node; if (gitn != null) { int rez = sizeof(byte) + GetSizeOfReference(gitn.original_generic) + sizeof(int); foreach (type_node par in gitn.instance_params) { rez += GetSizeOfReference(par); } return rez; } internal_interface ii = tn.get_internal_interface(internal_interface_kind.unsized_array_interface); if (ii != null) { return sizeof(byte) + 4 * 4 + GetSizeOfReference(tn.element_type) + 4; } return sizeof(byte) + sizeof(int); } private void VisitTypeDefinition(common_type_node type) { int offset = 0; if (is_interface == true) offset = SavePositionAndConstPool(type); else offset = SavePositionAndImplementationPool(type); bw.Write((byte)type.semantic_node_type); bw.Write(is_interface); bw.Write(type_entity_index++); if (is_interface == true) bw.Write(GetNameIndex(type)); else bw.Write(type.name); /*if (type.base_type != null) WriteTypeReference(type.base_type); else*/ //Пишем, является ли данный класс интерфейсом if (type.IsInterface) { bw.Write((byte)1); } else { bw.Write((byte)0); } //Пишем, является ли данный класс делегатом if (type.IsDelegate) { bw.Write((byte)1); } else { bw.Write((byte)0); } //Является ли тип описанием дженерика if (type.is_generic_type_definition) { bw.Write((byte)1); //Число типов-параметров bw.Write(type.generic_params.Count); //Имена параметров foreach (common_type_node par in type.generic_params) { bw.Write(par.name); } } else { bw.Write((byte)0); } int base_class_off = (int)bw.BaseStream.Position; bw.Seek(GetSizeOfReference(type.base_type), SeekOrigin.Current); //(ssyy) На кой чёрт это надо? //WriteTypeReference(SystemLibrary.SystemLibrary.object_type); //WriteTypeReference(type.base_type); bw.Write(type.internal_is_value); //Пишем поддерживаемые интерфейсы //eto nepravilno!!! a vdrug bazovye interfejsy eshe ne projdeny. //WriteImplementingInterfaces(type); int interface_impl_off = (int)bw.BaseStream.Position; int seek_off = sizeof(int); for (int k=0; k