// 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