//Метод, переводящий семантическое дерево в сборку .NET public void ConvertFromTree(SemanticTree.IProgramNode p, string TargetFileName, string SourceFileName, CompilerOptions options, string[] ResourceFiles) { //SystemLibrary.SystemLibInitializer.RestoreStandardFunctions(); bool RunOnly = false; string fname = TargetFileName; comp_opt = options; ad = Thread.GetDomain(); //получаем домен приложения //ad = ad.DomainManager.CreateDomain("D1", null, null); an = new AssemblyName(); //создаем имя сборки an.Version = new Version("1.0.0.0"); string dir = Directory.GetCurrentDirectory(); string source_name = fname;//p.Location.document.file_name; int pos = source_name.LastIndexOf(Path.DirectorySeparatorChar); if (pos != -1) //если имя файла указано с путем, то выделяем { dir = source_name.Substring(0, pos + 1); an.CodeBase = String.Concat("file:///", source_name.Substring(0, pos)); source_name = source_name.Substring(pos + 1); } string name = source_name.Substring(0, source_name.LastIndexOf('.')); if (comp_opt.target == TargetType.Exe || comp_opt.target == TargetType.WinExe) an.Name = name;// + ".exe"; else an.Name = name; //+ ".dll"; if (name == "PABCRtl" || name == "PABCRtl32") { an.Flags = AssemblyNameFlags.PublicKey; an.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess; an.HashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm.None; FileStream publicKeyStream = File.Open(Path.Combine(Path.GetDirectoryName(TargetFileName), name == "PABCRtl" ? "PublicKey.snk" : "PublicKey32.snk"), FileMode.Open); byte[] publicKey = new byte[publicKeyStream.Length]; publicKeyStream.Read(publicKey, 0, (int)publicKeyStream.Length); // Provide the assembly with a public key. an.SetPublicKey(publicKey); publicKeyStream.Close(); } if (RunOnly) ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run, dir);//определяем сборку else ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save, dir);//определяем сборку //int nn = ad.GetAssemblies().Length; if (options.NeedDefineVersionInfo) { ab.DefineVersionInfoResource(options.Product, options.ProductVersion, options.Company, options.Copyright, options.TradeMark); } if (options.MainResourceFileName != null) { try { ab.DefineUnmanagedResource(options.MainResourceFileName); } catch { throw new TreeConverter.SourceFileError(options.MainResourceFileName); } } else if (options.MainResourceData != null) { try { ab.DefineUnmanagedResource(options.MainResourceData); } catch { throw new TreeConverter.SourceFileError(""); } } save_debug_info = comp_opt.dbg_attrs == DebugAttributes.Debug || comp_opt.dbg_attrs == DebugAttributes.ForDebbuging; add_special_debug_variables = comp_opt.dbg_attrs == DebugAttributes.ForDebbuging; //bool emit_sym = true; if (save_debug_info) //если модуль отладочный, то устанавливаем атрибут, запрещающий inline методов ab.SetCustomAttribute(typeof(System.Diagnostics.DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new byte[] { 0x01, 0x00, 0x01, 0x01, 0x00, 0x00 }); //ab.SetCustomAttribute(typeof(System.Diagnostics.DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new byte[] { 0x01, 0x00, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00 }); //else // ab.SetCustomAttribute(typeof(System.Diagnostics.DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new byte[] { 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 }); if (RunOnly) mb = ab.DefineDynamicModule(name, save_debug_info); else { if (comp_opt.target == TargetType.Exe || comp_opt.target == TargetType.WinExe) mb = ab.DefineDynamicModule(name + ".exe", an.Name + ".exe", save_debug_info); //определяем модуль (save_debug_info - флаг включать отладочную информацию) else mb = ab.DefineDynamicModule(name + ".dll", an.Name + ".dll", save_debug_info); } cur_unit = Path.GetFileNameWithoutExtension(SourceFileName); string entry_cur_unit = cur_unit; entry_type = mb.DefineType(cur_unit + ".Program", TypeAttributes.Public);//определяем синтетический статический класс основной программы cur_type = entry_type; //точка входа в приложение if (p.main_function != null) { ConvertFunctionHeader(p.main_function); entry_meth = helper.GetMethod(p.main_function).mi as MethodBuilder; /*entry_meth = entry_type.DefineMethod(p.main_function.name, MethodAttributes.Public | MethodAttributes.Static, typeof(void), GetParamTypes(p.main_function)); for (int i = 0; i < p.main_function.parameters.Length; i++) { if (p.main_function.parameters[i].parameter_type == parameter_type.var) entry_meth.DefineParameter(i + 1, ParameterAttributes.Retval, p.main_function.parameters[i].name); else entry_meth.DefineParameter(i + 1, ParameterAttributes.None, p.main_function.parameters[i].name); }*/ cur_meth = entry_meth; il = cur_meth.GetILGenerator(); if (options.target != TargetType.Dll && options.dbg_attrs == DebugAttributes.ForDebbuging) AddSpecialInitDebugCode(); } ILGenerator tmp_il = il; MethodBuilder tmp_meth = cur_meth; //при отладке компилятора здесь иногда ничего нет! ICommonNamespaceNode[] cnns = p.namespaces; //создаем отладочные документы if (save_debug_info) { first_doc = mb.DefineDocument(SourceFileName, SymDocumentType.Text, SymLanguageType.Pascal, SymLanguageVendor.Microsoft); for (int iii = 0; iii < cnns.Length; iii++) { if (cnns[iii].Location != null) doc = mb.DefineDocument(cnns[iii].Location.document.file_name, SymDocumentType.Text, SymLanguageType.Pascal, SymLanguageVendor.Microsoft); else doc = first_doc; sym_docs.Add(cnns[iii], doc);//сохраняем его в таблице документов } first_doc = sym_docs[cnns[0]]; if (p.main_function != null) { if (p.main_function.function_code is IStatementsListNode) EntryPointLocation = ((IStatementsListNode)p.main_function.function_code).LeftLogicalBracketLocation; else EntryPointLocation = p.main_function.function_code.Location; } else EntryPointLocation = null; } ICommonNamespaceNode entry_ns = null; //Переводим заголовки типов for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii]]; bool is_main_namespace = cnns[iii].namespace_name == "" && comp_opt.target != TargetType.Dll || comp_opt.target == TargetType.Dll && cnns[iii].namespace_name == ""; ICommonNamespaceNode cnn = cnns[iii]; cur_type = entry_type; if (!is_main_namespace) cur_unit = cnn.namespace_name; else cur_unit = entry_cur_unit; if (iii == cnns.Length - 1 && comp_opt.target != TargetType.Dll || comp_opt.target == TargetType.Dll && iii == cnns.Length - 1) entry_ns = cnn; ConvertTypeHeaders(cnn.types); } //Переводим псевдоинстанции generic-типов foreach (ICommonTypeNode ictn in p.generic_type_instances) { ConvertTypeHeaderInSpecialOrder(ictn); } Dictionary<ICommonNamespaceNode, TypeBuilder> NamespacesTypes = new Dictionary<ICommonNamespaceNode, TypeBuilder>(); for (int iii = 0; iii < cnns.Length; iii++) { bool is_main_namespace = cnns[iii].namespace_name == "" && comp_opt.target != TargetType.Dll || comp_opt.target == TargetType.Dll && cnns[iii].namespace_name == ""; if (!is_main_namespace) { //определяем синтетический класс для модуля cur_type = mb.DefineType(cnns[iii].namespace_name + "." + cnns[iii].namespace_name, TypeAttributes.Public); types.Add(cur_type); NamespaceTypesList.Add(cur_type); NamespacesTypes.Add(cnns[iii], cur_type); if (cnns[iii].IsMain) { TypeBuilder attr_class = mb.DefineType(cnns[iii].namespace_name + "." + "$GlobAttr", TypeAttributes.Public | TypeAttributes.BeforeFieldInit, typeof(Attribute)); ConstructorInfo attr_ci = attr_class.DefineDefaultConstructor(MethodAttributes.Public); cur_type.SetCustomAttribute(attr_ci, new byte[4] { 0x01, 0x00, 0x00, 0x00 }); attr_class.CreateType(); } else { TypeBuilder attr_class = mb.DefineType(cnns[iii].namespace_name + "." + "$ClassUnitAttr", TypeAttributes.Public | TypeAttributes.BeforeFieldInit, typeof(Attribute)); ConstructorInfo attr_ci = attr_class.DefineDefaultConstructor(MethodAttributes.Public); cur_type.SetCustomAttribute(attr_ci, new byte[4] { 0x01, 0x00, 0x00, 0x00 }); attr_class.CreateType(); } } else { NamespacesTypes.Add(cnns[iii], entry_type); } } if (comp_opt.target == TargetType.Dll) { for (int iii = 0; iii < cnns.Length; iii++) { string tmp = cur_unit; if (cnns[iii].namespace_name != "") cur_unit = cnns[iii].namespace_name; else cur_unit = entry_cur_unit; foreach (ITemplateClass tc in cnns[iii].templates) { CreateTemplateClass(tc); } cur_unit = tmp; } for (int iii = 0; iii < cnns.Length; iii++) { string tmp = cur_unit; if (cnns[iii].namespace_name != "") cur_unit = cnns[iii].namespace_name; else cur_unit = entry_cur_unit; foreach (ITypeSynonym ts in cnns[iii].type_synonims) { CreateTypeSynonim(ts); } cur_unit = tmp; } } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii]]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; ConvertTypeMemberHeaders(cnns[iii].types); // cur_type = NamespacesTypes[cnns[iii]]; // cur_unit_type = NamespacesTypes[cnns[iii]]; // ConvertFunctionHeaders(cnns[iii].functions); } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii]]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; ConvertFunctionHeaders(cnns[iii].functions); } if (p.InitializationCode != null) { tmp_il = il; if (entry_meth != null) { il = entry_meth.GetILGenerator(); ConvertStatement(p.InitializationCode); } else { //il = unit_cci.GetILGenerator(); //ConvertStatement(p.InitializationCode); } il = tmp_il; } //Переводим псевдоинстанции generic-типов foreach (IGenericTypeInstance ictn in p.generic_type_instances) { ConvertGenericInstanceTypeMembers(ictn); } //Переводим псевдоинстанции функций foreach (IGenericFunctionInstance igfi in p.generic_function_instances) { ConvertGenericFunctionInstance(igfi); } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii]]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; //генерим инциализацию для полей foreach (SemanticTree.ICommonTypeNode ctn in cnns[iii].types) GenerateInitCodeForFields(ctn); } ConstructorBuilder unit_cci = null; //Переводим заголовки всего остального (процедур, переменных) for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii]]; bool is_main_namespace = iii == cnns.Length - 1 && comp_opt.target != TargetType.Dll; ICommonNamespaceNode cnn = cnns[iii]; string tmp_unit_name = cur_unit; if (!is_main_namespace) cur_unit = cnn.namespace_name; else cur_unit = entry_cur_unit; cur_type = NamespacesTypes[cnn]; //ConvertFunctionHeaders(cnn.functions); if (!is_main_namespace) { //определяем статический конструктор класса для модуля ConstructorBuilder cb = cur_type.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); il = cb.GetILGenerator(); if (cnn.IsMain) unit_cci = cb; ModulesInitILGenerators.Add(cur_type, il); //переводим глобальные переменные модуля ConvertGlobalVariables(cnn.variables); //перводим константы ConvertNamespaceConstants(cnn.constants); ConvertNamespaceEvents(cnn.events); //il.Emit(OpCodes.Ret); } else { //Не нарвится мне порядок вызова. надо с этим разобраться init_variables_mb = helper.GetMethodBuilder(cnn.functions[cnn.functions.Length-1]);// cur_type.DefineMethod("$InitVariables", MethodAttributes.Public | MethodAttributes.Static); il = entry_meth.GetILGenerator(); ModulesInitILGenerators.Add(cur_type, il); il = init_variables_mb.GetILGenerator(); ConvertGlobalVariables(cnn.variables); il = entry_meth.GetILGenerator(); //перводим константы ConvertNamespaceConstants(cnn.constants); ConvertNamespaceEvents(cnn.events); //il.Emit(OpCodes.Ret); } cur_unit = tmp_unit_name; } if (p.InitializationCode != null) { tmp_il = il; if (entry_meth == null) { il = unit_cci.GetILGenerator(); ConvertStatement(p.InitializationCode); } il = tmp_il; } cur_type = entry_type; //is_in_unit = false; //переводим реализации for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii]]; bool is_main_namespace = iii == 0 && comp_opt.target != TargetType.Dll; ICommonNamespaceNode cnn = cnns[iii]; string tmp_unit_name = cur_unit; if (!is_main_namespace) cur_unit = cnn.namespace_name; //if (iii > 0) is_in_unit = true; cur_unit_type = NamespacesTypes[cnns[iii]]; cur_type = cur_unit_type; ConvertTypeImplementations(cnn.types); ConvertFunctionsBodies(cnn.functions); cur_unit = tmp_unit_name; } if (comp_opt.target != TargetType.Dll && p.main_function != null) { cur_unit_type = NamespacesTypes[cnns[0]]; cur_type = cur_unit_type; ConvertBody(p.main_function.function_code); } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii]]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; //вставляем ret в int_meth foreach (SemanticTree.ICommonTypeNode ctn in cnns[iii].types) GenerateRetForInitMeth(ctn); ModulesInitILGenerators[cur_type].Emit(OpCodes.Ret); } for (int iii = 0; iii < cnns.Length; iii++) { MakeAttribute(cnns[iii]); } doc = first_doc; cur_type = entry_type; // il = entry_type.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes).GetILGenerator(); // if (p.InitializationCode != null) // ConvertStatement(p.InitializationCode); /*cur_meth = entry_meth; il = entry_meth.GetILGenerator(); //переводим тело основной программы //Тут только вызовы init, final if (p.main_function != null) { ConvertBody(p.main_function.function_code); il.Emit(OpCodes.Ret); }*/ CloseTypes();//закрываем типы entry_type.CreateType(); switch (comp_opt.target) { case TargetType.Exe: ab.SetEntryPoint(entry_meth, PEFileKinds.ConsoleApplication); break; case TargetType.WinExe: if (!comp_opt.ForRunningWithEnvironment) ab.SetEntryPoint(entry_meth, PEFileKinds.WindowApplication); else ab.SetEntryPoint(entry_meth, PEFileKinds.ConsoleApplication); break; } /**/ try { //ne osobo vazhnaja vesh, sohranjaet v exe-shnik spisok ispolzuemyh prostranstv imen, dlja strahovki obernuli try catch if (comp_opt.dbg_attrs == DebugAttributes.ForDebbuging) { string[] namespaces = p.UsedNamespaces; TypeBuilder attr_class = mb.DefineType("$UsedNsAttr", TypeAttributes.Public | TypeAttributes.BeforeFieldInit, typeof(Attribute)); FieldBuilder fld_ns = attr_class.DefineField("ns", TypeFactory.StringType, FieldAttributes.Public); FieldBuilder fld_count = attr_class.DefineField("count", TypeFactory.Int32Type, FieldAttributes.Public); ConstructorBuilder attr_ci = attr_class.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[2] { TypeFactory.Int32Type, TypeFactory.StringType }); ILGenerator attr_il = attr_ci.GetILGenerator(); attr_il.Emit(OpCodes.Ldarg_0); attr_il.Emit(OpCodes.Ldarg_1); attr_il.Emit(OpCodes.Stfld, fld_count); attr_il.Emit(OpCodes.Ldarg_0); attr_il.Emit(OpCodes.Ldarg_2); attr_il.Emit(OpCodes.Stfld, fld_ns); attr_il.Emit(OpCodes.Ret); int len = 2 + 2 + 4 + 1; foreach (string ns in namespaces) { len += ns.Length + 1; } byte[] bytes = new byte[len]; bytes[0] = 1; bytes[1] = 0; using (BinaryWriter bw = new BinaryWriter(new MemoryStream())) { bw.Write(namespaces.Length); System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach (string ns in namespaces) { sb.Append(Convert.ToChar(ns.Length)); sb.Append(ns); //bw.Write(ns); } if (sb.Length > 127) { len += 1; bytes = new byte[len]; bytes[0] = 1; bytes[1] = 0; } bw.Write(sb.ToString()); bw.Seek(0, SeekOrigin.Begin); bw.BaseStream.Read(bytes, 2, len - 4); if (sb.Length > 127) { bytes[7] = (byte)(sb.Length & 0xFF); bytes[6] = (byte)(0x80 | ((sb.Length & 0xFF00) >> 8)); } } entry_type.SetCustomAttribute(attr_ci, bytes); attr_class.CreateType(); } } catch (Exception e) { } if (an.Name == "PABCRtl" || an.Name == "PABCRtl32") { CustomAttributeBuilder cab = new CustomAttributeBuilder(typeof(AssemblyKeyFileAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { an.Name == "PABCRtl" ? "PublicKey.snk" : "PublicKey32.snk" }); ab.SetCustomAttribute(cab); cab = new CustomAttributeBuilder(typeof(AssemblyDelaySignAttribute).GetConstructor(new Type[] { typeof(bool) }), new object[] { true }); ab.SetCustomAttribute(cab); cab = new CustomAttributeBuilder(typeof(TargetFrameworkAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { ".NETFramework,Version=v4.0" }); ab.SetCustomAttribute(cab); } ab.SetCustomAttribute(new CustomAttributeBuilder(typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) }), new object[] { SecurityRuleSet.Level2 }, new PropertyInfo[] { typeof(SecurityRulesAttribute).GetProperty("SkipVerificationInFullTrust") }, new object[] { true })); /*ab.SetCustomAttribute(new CustomAttributeBuilder(typeof(System.Security.Permissions.SecurityPermissionAttribute).GetConstructor(new Type[] { typeof(System.Security.Permissions.SecurityAction) }), new object[] { System.Security.Permissions.SecurityAction.RequestMinimum }, new PropertyInfo[] { typeof(System.Security.Permissions.SecurityPermissionAttribute).GetProperty("UnmanagedCode") }, new object[] { true }));*/ if (entry_meth != null && comp_opt.target == TargetType.WinExe) { entry_meth.SetCustomAttribute(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), new byte[] { 0x01, 0x00, 0x00, 0x00 }); } List<FileStream> ResStreams = new List<FileStream>(); if (ResourceFiles != null) foreach (string resname in ResourceFiles) { FileStream stream = File.OpenRead(resname); ResStreams.Add(stream); mb.DefineManifestResource(Path.GetFileName(resname), stream, ResourceAttributes.Public); //System.Resources.ResourceManager rm; //System.Resources.ResourceSet rs;rs. } ab.SetCustomAttribute(typeof(System.Runtime.CompilerServices.CompilationRelaxationsAttribute).GetConstructor(new Type[1] { TypeFactory.Int32Type }), new byte[] { 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }); //ab.SetCustomAttribute(typeof(System.Runtime.CompilerServices.RuntimeCompatibilityAttribute, if (RunOnly) { object main_class = ab.CreateInstance(cur_unit + ".Program"); MethodInfo methodInfo = main_class.GetType().GetMethod("Main"); //AppDomain.CreateDomain( methodInfo.Invoke(main_class, null); //ad.ExecuteAssemblyByName(assembly_to_run.GetName(), new System.Security.Policy.Evidence(), null); } else { int tries = 0; bool not_done = true; do { try { if (comp_opt.target == TargetType.Exe || comp_opt.target == TargetType.WinExe) { if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x86) ab.Save(an.Name + ".exe", PortableExecutableKinds.Required32Bit, ImageFileMachine.I386); //else if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x64) // ab.Save(an.Name + ".exe", PortableExecutableKinds.PE32Plus, ImageFileMachine.IA64); else ab.Save(an.Name + ".exe"); //сохраняем сборку } else { if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x86) ab.Save(an.Name + ".dll", PortableExecutableKinds.Required32Bit, ImageFileMachine.I386); //else if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x64) // ab.Save(an.Name + ".dll", PortableExecutableKinds.PE32Plus, ImageFileMachine.IA64); else ab.Save(an.Name + ".dll"); } not_done = false; } catch (System.Runtime.InteropServices.COMException e) { throw new TreeConverter.SaveAssemblyError(e.Message); } catch (System.IO.IOException e) { if (tries < num_try_save) tries++; else throw new TreeConverter.SaveAssemblyError(e.Message); } } while (not_done); } foreach (FileStream fs in ResStreams) fs.Close(); //ad.ExecuteAssemblyByName(an, new System.Security.Policy.Evidence()); //это уже не нужно //Console.WriteLine(Environment.TickCount-ticks); }
public string Compile() { try { //var timer = System.Diagnostics.Stopwatch.StartNew(); ////// if (Path.GetExtension(CompilerOptions.SourceFileName) == ".vb") { return CompileVB(); } if (Path.GetExtension(CompilerOptions.SourceFileName) == ".cs") { return CompileCS(); } OnChangeCompilerState(this, CompilerState.CompilationStarting, CompilerOptions.SourceFileName); Reset(); //Console.WriteLine(timer.ElapsedMilliseconds / 1000.0); ////// if (CompilerOptions.ProjectCompiled) { PrepareCompileOptionsForProject(); } Environment.CurrentDirectory = CompilerOptions.SourceFileDirectory; // нужно для подключения *.inc и *.resources Units = new PascalABCCompiler.TreeRealization.unit_node_list(); CurrentSyntaxUnit = new SyntaxTree.uses_unit_in(new SyntaxTree.string_const(CompilerOptions.SourceFileName)); CompileUnit(Units, CurrentSyntaxUnit); //Console.WriteLine(timer.ElapsedMilliseconds / 1000.0); ////// foreach (CompilationUnit CurrentUnit in UnitsToCompile) if (CurrentUnit.State != UnitState.Compiled) { CurrentCompilationUnit = CurrentUnit; string UnitName = GetUnitFileName(CurrentUnit.SyntaxUnitName); //if(CurrentUnit.State!=UnitState.InterfaceCompiled) //DEBUG //Console.WriteLine("ERROR! interface not compiled "+GetUnitFileName(CurrentUnit.SyntaxUnitName));//DEBUG System.Collections.Generic.List<SyntaxTree.unit_or_namespace> SyntaxUsesList = GetSyntaxImplementationUsesList(CurrentUnit.SyntaxTree); CurrentUnit.PossibleNamespaces.Clear(); if (SyntaxUsesList != null) { for (int i = SyntaxUsesList.Count - 1; i >= 0; i--) if (!IsPossibleNamespace(SyntaxUsesList[i], false)) { compilerOptions.UseDllForSystemUnits = false; break; } for (int i = SyntaxUsesList.Count - 1; i >= 0; i--) if (!IsPossibleNamespace(SyntaxUsesList[i], true)) CompileUnit(CurrentUnit.ImplementationUsedUnits, SyntaxUsesList[i]); else { CurrentUnit.ImplementationUsedUnits.AddElement(new TreeRealization.namespace_unit_node(GetNamespace(SyntaxUsesList[i]))); CurrentUnit.PossibleNamespaces.Add(SyntaxUsesList[i]); } } //Console.WriteLine("Compile Implementation "+UnitName);//DEBUG //TODO: Избавиться от преобразования типа. AddNamespaces(CurrentUnit.ImplementationUsingNamespaceList, CurrentUnit.PossibleNamespaces, true); #if DEBUG if (InternalDebug.SemanticAnalysis) #endif { OnChangeCompilerState(this, CompilerState.CompileImplementation, UnitName); PascalABCCompiler.TreeConverter.SemanticRules.SymbolTableCaseSensitive = CurrentUnit.CaseSensitive; SyntaxTreeToSemanticTreeConverter.CompileImplementation( (PascalABCCompiler.TreeRealization.common_unit_node)CurrentUnit.SemanticTree, CurrentUnit.SyntaxTree, buildImplementationUsesList(CurrentUnit), ErrorsList,Warnings, CurrentUnit.syntax_error, BadNodesInSyntaxTree, CurrentUnit.InterfaceUsingNamespaceList, CurrentUnit.ImplementationUsingNamespaceList, null, CompilerOptions.Debug, CompilerOptions.ForDebugging ); CheckErrors(); } CurrentUnit.State = UnitState.Compiled; OnChangeCompilerState(this, CompilerState.EndCompileFile, UnitName); //SavePCU(CurrentUnit, UnitName); CurrentUnit.UnitName = UnitName; } ClosePCUReadersAndWriters(); if (CompilerOptions.SaveDocumentation) SaveDocumentations(); compilerDirectives = GetCompilerDirectives(UnitsSortedList); TreeRealization.compiler_directive compilerDirective; //TODO сделать это понормальному!!!!! if (compilerDirectives.ContainsKey(TreeConverter.compiler_string_consts.compiler_directive_apptype)) { string directive = compilerDirectives[TreeConverter.compiler_string_consts.compiler_directive_apptype][0].directive; if (string.Compare(directive,"console",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.ConsoleApplicaton; else if (string.Compare(directive,"windows",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.WindowsApplication; else if (string.Compare(directive,"dll",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.ClassLibrary; else if (string.Compare(directive,"pcu",true)==0) CompilerOptions.OutputFileType = CompilerOptions.OutputType.PascalCompiledUnit; } moveSystemUnitToForwardUnitSortedList(); PascalABCCompiler.TreeRealization.common_unit_node system_unit = null; if (UnitsSortedList.Count>0) system_unit = UnitsSortedList[0].SemanticTree as PascalABCCompiler.TreeRealization.common_unit_node; if (system_unit != null) system_unit.IsConsoleApplicationVariable = CompilerOptions.OutputFileType == CompilerOptions.OutputType.ConsoleApplicaton; TreeRealization.program_node pn = null; NETGenerator.CompilerOptions cdo = new NETGenerator.CompilerOptions(); List<TreeRealization.compiler_directive> cds; if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.compiler_directive_platformtarget, out cds)) { string plt = cds[0].directive.ToLower(); if (plt.Equals("x86")) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.x86; else if (plt.Equals("x64")) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.x64; else if (plt.Equals("anycpu")) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.AnyCPU; } if (this.compilerOptions.Only32Bit) cdo.platformtarget = NETGenerator.CompilerOptions.PlatformTarget.x86; if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.product_string, out cds)) { cdo.Product = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.version_string, out cds)) { cdo.ProductVersion = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.company_string, out cds)) { cdo.Company = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.trademark_string, out cds)) { cdo.TradeMark = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.copyright_string, out cds)) { cdo.Copyright = cds[0].directive; } if (compilerDirectives.TryGetValue(TreeConverter.compiler_string_consts.main_resource_string, out cds)) { cdo.MainResourceFileName = cds[0].directive; if (!File.Exists(cdo.MainResourceFileName)) { ErrorsList.Add(new ResourceFileNotFound(cds[0].directive, cds[0].location)); } } List<string> ResourceFiles = null; if (compilerDirectives.ContainsKey(TreeConverter.compiler_string_consts.compiler_directive_resource)) { ResourceFiles = new List<string>(); List<TreeRealization.compiler_directive> ResourceDirectives = compilerDirectives[TreeConverter.compiler_string_consts.compiler_directive_resource]; foreach (TreeRealization.compiler_directive cd in ResourceDirectives) if (!File.Exists(cd.directive)) { string fileName = Path.Combine(cd.location.doc.file_name, cd.directive); if (File.Exists(fileName)) ResourceFiles.Add(fileName); else ErrorsList.Add(new ResourceFileNotFound(cd.directive, cd.location)); } else ResourceFiles.Add(cd.directive); } string res_file = null; if (project != null) { if (!(project.major_version == 0 && project.minor_version == 0 && project.build_version == 0 && project.revision_version == 0)) cdo.ProductVersion = project.major_version + "." + project.minor_version + "." + project.build_version + "." + project.revision_version; if (!string.IsNullOrEmpty(project.product)) cdo.Product = project.product; if (!string.IsNullOrEmpty(project.company)) cdo.Company = project.company; if (!string.IsNullOrEmpty(project.trademark)) cdo.TradeMark = project.trademark; if (!string.IsNullOrEmpty(project.copyright)) cdo.Copyright = project.copyright; if (!string.IsNullOrEmpty(project.app_icon) && false) { //cdo.MainResourceFileName = project.app_icon; string rc_file = Path.GetFileNameWithoutExtension(project.app_icon) + ".rc"; StreamWriter sw = File.CreateText(rc_file); sw.WriteLine("1 ICON \"" + project.app_icon.Replace("\\", "\\\\") + "\""); if (cdo.NeedDefineVersionInfo) { cdo.NeedDefineVersionInfo = false; sw.WriteLine("1 VERSIONINFO"); string ver = project.major_version + "," + project.minor_version + "," + project.build_version + "," + project.revision_version; sw.WriteLine("FILEVERSION " + ver); /*sw.WriteLine("FILEFLAGSMASK VS_FFI_FILEFLAGSMASK"); sw.WriteLine("FILEFLAGS VER_DEBUG"); sw.WriteLine("FILEOS VOS__WINDOWS32"); if (project.project_type != ProjectType.Library) sw.WriteLine("FILETYPE VFT_APP"); else sw.WriteLine("FILETYPE VFT_DLL"); sw.WriteLine("FILESUBTYPE VFT2_UNKNOWN");*/ sw.WriteLine("BEGIN \r\n BLOCK \"StringFileInfo\"\r\n BEGIN \r\n BLOCK \"041904E3\"\r\nBEGIN"); sw.WriteLine("VALUE \"ProductName\"," + "\"" + cdo.Product + "\""); sw.WriteLine("VALUE \"FileVersion\"," + "\"" + ver + "\""); sw.WriteLine("VALUE \"ProductVersion\"," + "\"" + ver + "\""); sw.WriteLine("VALUE \"FileDescription\"," + "\"" + "" + "\""); sw.WriteLine("VALUE \"OriginalFileName\"," + "\"" + Path.GetFileName(CompilerOptions.OutputFileName) + "\""); sw.WriteLine("VALUE \"InternalName\"," + "\"" + Path.GetFileNameWithoutExtension(CompilerOptions.OutputFileName) + "\""); sw.WriteLine("VALUE \"CompanyName\"," + "\"" + cdo.Company + "\""); sw.WriteLine("VALUE \"LegalTrademarks1\"," + "\"" + cdo.TradeMark + "\""); sw.WriteLine("VALUE \"LegalCopyright\"," + "\"" + cdo.Copyright + "\""); sw.WriteLine("END"); sw.WriteLine("END"); sw.WriteLine("BLOCK \"VarFileInfo\"\r\nBEGIN"); sw.WriteLine("VALUE \"Translation\", 0x0419, 1251"); sw.WriteLine("END"); sw.WriteLine("END"); } sw.Close(); System.Diagnostics.Process prc = new System.Diagnostics.Process(); prc.StartInfo.FileName = Path.Combine(this.CompilerOptions.SystemDirectory, "rc.exe"); prc.StartInfo.Arguments = Path.Combine(Path.GetDirectoryName(project.app_icon), Path.GetFileNameWithoutExtension(project.app_icon) + ".rc"); prc.StartInfo.CreateNoWindow = true; prc.StartInfo.UseShellExecute = false; prc.StartInfo.RedirectStandardOutput = true; prc.StartInfo.RedirectStandardError = true; prc.Start(); prc.WaitForExit(); res_file = Path.Combine(Path.GetDirectoryName(project.app_icon), Path.GetFileNameWithoutExtension(project.app_icon) + ".res"); if (File.Exists(res_file)) { cdo.MainResourceFileName = res_file; } File.Delete(rc_file); } } if (ErrorsList.Count == 0 && compilerOptions.GenerateCode) { cdo.ForRunningWithEnvironment = CompilerOptions.RunWithEnvironment; switch (CompilerOptions.OutputFileType) { case CompilerOptions.OutputType.ClassLibrary: cdo.target = NETGenerator.TargetType.Dll; break; case CompilerOptions.OutputType.ConsoleApplicaton: cdo.target = NETGenerator.TargetType.Exe; break; case CompilerOptions.OutputType.WindowsApplication: cdo.target = NETGenerator.TargetType.WinExe; break; } if (project != null && project.ProjectType == ProjectType.WindowsApp) cdo.target = PascalABCCompiler.NETGenerator.TargetType.WinExe; switch (CompilerOptions.Debug) { case true: cdo.dbg_attrs = NETGenerator.DebugAttributes.Debug; break; case false: cdo.dbg_attrs = NETGenerator.DebugAttributes.Release; break; } if (CompilerOptions.ForDebugging) cdo.dbg_attrs = NETGenerator.DebugAttributes.ForDebbuging; //TODO: Разобратся c location для program_node и правильно передавать main_function. Добавить генератор main_function в SyntaxTreeToSemanticTreeConverter. pn = new PascalABCCompiler.TreeRealization.program_node(null, null); for (int i = 0; i < UnitsSortedList.Count; i++) pn.units.AddElement(UnitsSortedList[i].SemanticTree as TreeRealization.common_unit_node); //(ssyy) Добавил в условие c_module if (FirstCompilationUnit.SyntaxTree is SyntaxTree.program_module || FirstCompilationUnit.SyntaxTree is SyntaxTree.c_module) { if ((cdo.target == NETGenerator.TargetType.Exe) || (cdo.target == NETGenerator.TargetType.WinExe)) { if (UnitsSortedList.Count > 0) { pn.main_function = ((PascalABCCompiler.TreeRealization.common_unit_node)UnitsSortedList[UnitsSortedList.Count - 1].SemanticTree).main_function; /***************************Ivan added*******************************/ if (pn.main_function.function_code.location != null) { bool flag = false; PascalABCCompiler.TreeRealization.common_namespace_node main_ns = pn.main_function.namespace_node; for (int i = 0; i < main_ns.variables.Count; i++) { PascalABCCompiler.TreeRealization.namespace_variable nv = main_ns.variables[i]; if (nv.inital_value != null && nv.inital_value.location != null && !(nv.inital_value is PascalABCCompiler.TreeRealization.constant_node) && !(nv.inital_value is PascalABCCompiler.TreeRealization.record_initializer) && !(nv.inital_value is PascalABCCompiler.TreeRealization.array_initializer)) { varBeginOffset = main_ns.variables[i].inital_value.location.begin_line_num; flag = true; break; } } beginOffset = pn.main_function.function_code.location.begin_line_num; } /*******************************************************************/ Dictionary<string, object> config_dic = new Dictionary<string, object>(); if (CompilerOptions.Locale != null && PascalABCCompiler.StringResourcesLanguage.GetLCIDByTwoLetterISO(CompilerOptions.Locale) != null) { config_dic["locale"] = CompilerOptions.Locale; config_dic["full_locale"] = PascalABCCompiler.StringResourcesLanguage.GetLCIDByTwoLetterISO(CompilerOptions.Locale); } pn.create_main_function(StandarModules.ToArray(), config_dic); } } } else if (FirstCompilationUnit.SyntaxTree is SyntaxTree.unit_module && cdo.target == NETGenerator.TargetType.Dll) { pn.create_main_function_as_in_module(); } pn = semanticTreeConvertersController.Convert(pn) as TreeRealization.program_node; _semantic_tree = pn; if (FirstCompilationUnit.SyntaxTree is SyntaxTree.unit_module && CompilerOptions.OutputFileType != CompilerOptions.OutputType.ClassLibrary) { //если мы комилируем PCU CompilerOptions.OutputFileType = CompilerOptions.OutputType.PascalCompiledUnit; } else { if( CompilerOptions.OutputFileType!= CompilerOptions.OutputType.SemanticTree) #if DEBUG if (InternalDebug.CodeGeneration) #endif { try { File.Create(CompilerOptions.OutputFileName).Close(); //File.Delete(CompilerOptions.OutputFileName); string pdb_file_name=Path.ChangeExtension(CompilerOptions.OutputFileName, ".pdb"); if (File.Exists(pdb_file_name)) File.Delete(pdb_file_name); } catch (Exception) { throw new UnauthorizedAccessToFile(CompilerOptions.OutputFileName); } OnChangeCompilerState(this, CompilerState.CodeGeneration, CompilerOptions.OutputFileName); string[] ResourceFilesArray = null; if (ResourceFiles != null) ResourceFilesArray = ResourceFiles.ToArray(); cds = null; /*if (compilerDirectives.TryGetValue("platform", out cds) && cds[0].directive.ToLower() == "native") { //LLVMCodeGeneratorsController.Compile(pn, CompilerOptions.OutputFileName, CompilerOptions.SourceFileName, ResourceFilesArray); PABCToCppCodeGeneratorsController.Compile(pn, CompilerOptions.OutputFileName, CompilerOptions.SourceFileName, ResourceFilesArray); } else*/ CodeGeneratorsController.Compile(pn, CompilerOptions.OutputFileName, CompilerOptions.SourceFileName, cdo, CompilerOptions.StandartDirectories, ResourceFilesArray); if (res_file != null) File.Delete(res_file); } } } } catch (TreeConverter.ParserError err) { //конвертор уткнулся в ошибку. ничего не делаем } catch (Errors.CompilerInternalError err) { if (ErrorsList.Count == 0) ErrorsList.Add(err); else { #if DEBUG if (!InternalDebug.SkipInternalErrorsIfSyntaxTreeIsCorrupt) ErrorsList.Add(err); #endif } } catch (Errors.Error err) { if (ErrorsList.Count == 0) ErrorsList.Add(err); else if (err != ErrorsList[0]) { if (err is SemanticError) { int pos = ErrorsList.Count; SourceLocation loc = (err as SemanticError).SourceLocation, loctmp; if (loc != null) for (int i = 0; i < ErrorsList.Count; i++) if (ErrorsList[i] is LocatedError) if ((loctmp = (ErrorsList[i] as LocatedError).SourceLocation) != null) if (loctmp > loc) { pos = i; break; } ErrorsList.Insert(pos, err); } else ErrorsList.Add(err); } } catch (Exception err) { string fn = "Compiler"; if (CurrentCompilationUnit != null && this.CurrentCompilationUnit.SyntaxTree != null) fn = Path.GetFileName(this.CurrentCompilationUnit.SyntaxTree.file_name); Errors.CompilerInternalError comp_err = new Errors.CompilerInternalError(string.Format("Compiler.Compile[{0}]", fn), err); if (ErrorsList.Count == 0) ErrorsList.Add(comp_err); else { #if DEBUG if (!InternalDebug.SkipInternalErrorsIfSyntaxTreeIsCorrupt) ErrorsList.Add(comp_err); #endif } } //удаляем лишние ошибки /*foreach(Error er in errorsList) { }*/ //на случай если мы вывалились по исключению но у нас есть откомпилированные модули try { ClosePCUReadersAndWriters(); } catch (Exception e) { ErrorsList.Add(new Errors.CompilerInternalError("Compiler.ClosePCUReadersAndWriters", e)); } bool need_recompiled = false; if (ErrorsList.Count > 0) { if (compilerOptions.UseDllForSystemUnits && !has_only_syntax_errors(ErrorsList) && compilerOptions.IgnoreRtlErrors) { compilerOptions.UseDllForSystemUnits = false; ErrorsList.Clear(); need_recompiled = true; } } OnChangeCompilerState(this, CompilerState.CompilationFinished, CompilerOptions.SourceFileName); if (ClearAfterCompilation) ClearAll(); OnChangeCompilerState(this, CompilerState.Ready, null); if (ErrorsList.Count > 0) { return null; } else if (need_recompiled) { //Compiler c = new Compiler(sourceFilesProvider,OnChangeCompilerState); //return c.Compile(this.compilerOptions); return Compile(); } else return CompilerOptions.OutputFileName; }
//Метод, переводящий семантическое дерево в сборку .NET public void ConvertFromTree(SemanticTree.IProgramNode p, string TargetFileName, string SourceFileName, CompilerOptions options, string[] ResourceFiles) { //SystemLibrary.SystemLibInitializer.RestoreStandardFunctions(); bool RunOnly = false; string fname = TargetFileName; comp_opt = options; ad = Thread.GetDomain(); //получаем домен приложения an = new AssemblyName(); //создаем имя сборки an.Version = new Version("1.0.0.0"); string dir = Directory.GetCurrentDirectory(); string source_name = fname;//p.Location.document.file_name; int pos = source_name.LastIndexOf(Path.DirectorySeparatorChar); if (pos != -1) //если имя файла указано с путем, то выделяем { dir = source_name.Substring(0, pos + 1); an.CodeBase = String.Concat("file:///", source_name.Substring(0, pos)); source_name = source_name.Substring(pos + 1); } string name = source_name.Substring(0, source_name.LastIndexOf('.')); if (comp_opt.target == TargetType.Exe || comp_opt.target == TargetType.WinExe) an.Name = name;// + ".exe"; else an.Name = name; //+ ".dll"; if (name == "PABCRtl" || name == "PABCRtl32") { an.Flags = AssemblyNameFlags.PublicKey; an.VersionCompatibility = System.Configuration.Assemblies.AssemblyVersionCompatibility.SameProcess; an.HashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm.None; FileStream publicKeyStream = File.Open(Path.Combine(Path.GetDirectoryName(TargetFileName), name == "PABCRtl" ? "PublicKey.snk" : "PublicKey32.snk"), FileMode.Open); byte[] publicKey = new byte[publicKeyStream.Length]; publicKeyStream.Read(publicKey, 0, (int)publicKeyStream.Length); // Provide the assembly with a public key. an.SetPublicKey(publicKey); publicKeyStream.Close(); } if (RunOnly) ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run, dir);//определяем сборку else ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Save, dir);//определяем сборку //int nn = ad.GetAssemblies().Length; if (options.NeedDefineVersionInfo) { ab.DefineVersionInfoResource(options.Product, options.ProductVersion, options.Company, options.Copyright, options.TradeMark); } if (options.MainResourceFileName != null) { try { ab.DefineUnmanagedResource(options.MainResourceFileName); } catch { throw new TreeConverter.SourceFileError(options.MainResourceFileName); } } else if (options.MainResourceData != null) { try { ab.DefineUnmanagedResource(options.MainResourceData); } catch { throw new TreeConverter.SourceFileError(""); } } save_debug_info = comp_opt.dbg_attrs == DebugAttributes.Debug || comp_opt.dbg_attrs == DebugAttributes.ForDebbuging; add_special_debug_variables = comp_opt.dbg_attrs == DebugAttributes.ForDebbuging; //bool emit_sym = true; if (save_debug_info) //если модуль отладочный, то устанавливаем атрибут, запрещающий inline методов ab.SetCustomAttribute(typeof(System.Diagnostics.DebuggableAttribute).GetConstructor(new Type[] { typeof(bool), typeof(bool) }), new byte[] { 0x01, 0x00, 0x01, 0x01, 0x00, 0x00 }); if (RunOnly) mb = ab.DefineDynamicModule(name, save_debug_info); else { if (comp_opt.target == TargetType.Exe || comp_opt.target == TargetType.WinExe) mb = ab.DefineDynamicModule(name + ".exe", an.Name + ".exe", save_debug_info); //определяем модуль (save_debug_info - флаг включать отладочную информацию) else mb = ab.DefineDynamicModule(name + ".dll", an.Name + ".dll", save_debug_info); } cur_unit = Path.GetFileNameWithoutExtension(SourceFileName); string entry_cur_unit = cur_unit; entry_type = mb.DefineType(cur_unit + ".Program", TypeAttributes.Public);//определяем синтетический статический класс основной программы cur_type = entry_type; //точка входа в приложение if (p.main_function != null) { ConvertFunctionHeader(p.main_function); entry_meth = helper.GetMethod(p.main_function).mi as MethodBuilder; cur_meth = entry_meth; il = cur_meth.GetILGenerator(); if (options.target != TargetType.Dll && options.dbg_attrs == DebugAttributes.ForDebbuging) AddSpecialInitDebugCode(); } ILGenerator tmp_il = il; MethodBuilder tmp_meth = cur_meth; //при отладке компилятора здесь иногда ничего нет! ICommonNamespaceNode[] cnns = p.namespaces; //создаем отладочные документы if (save_debug_info) { first_doc = mb.DefineDocument(SourceFileName, SymDocumentType.Text, SymLanguageType.Pascal, SymLanguageVendor.Microsoft); sym_docs.Add(SourceFileName, first_doc); for (int iii = 0; iii < cnns.Length; iii++) { string cnns_document_file_name = null; if (cnns[iii].Location != null) { cnns_document_file_name = cnns[iii].Location.document.file_name; doc = mb.DefineDocument(cnns_document_file_name, SymDocumentType.Text, SymLanguageType.Pascal, SymLanguageVendor.Microsoft); } else doc = first_doc; if (!sym_docs.ContainsKey(cnns_document_file_name)) sym_docs.Add(cnns_document_file_name, doc);//сохраняем его в таблице документов } first_doc = sym_docs[cnns[0].Location == null ? SourceFileName : cnns[0].Location.document.file_name]; if (p.main_function != null) { if (p.main_function.function_code is IStatementsListNode) EntryPointLocation = ((IStatementsListNode)p.main_function.function_code).LeftLogicalBracketLocation; else EntryPointLocation = p.main_function.function_code.Location; } else EntryPointLocation = null; } ICommonNamespaceNode entry_ns = null; //Переводим заголовки типов for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii].Location == null ? SourceFileName : cnns[iii].Location.document.file_name]; bool is_main_namespace = cnns[iii].namespace_name == "" && comp_opt.target != TargetType.Dll || comp_opt.target == TargetType.Dll && cnns[iii].namespace_name == ""; ICommonNamespaceNode cnn = cnns[iii]; cur_type = entry_type; if (!is_main_namespace) cur_unit = cnn.namespace_name; else cur_unit = entry_cur_unit; if (iii == cnns.Length - 1 && comp_opt.target != TargetType.Dll || comp_opt.target == TargetType.Dll && iii == cnns.Length - 1) entry_ns = cnn; ConvertTypeHeaders(cnn.types); } //Переводим псевдоинстанции generic-типов foreach (ICommonTypeNode ictn in p.generic_type_instances) { ConvertTypeHeaderInSpecialOrder(ictn); } Dictionary<ICommonNamespaceNode, TypeBuilder> NamespacesTypes = new Dictionary<ICommonNamespaceNode, TypeBuilder>(); for (int iii = 0; iii < cnns.Length; iii++) { bool is_main_namespace = cnns[iii].namespace_name == "" && comp_opt.target != TargetType.Dll || comp_opt.target == TargetType.Dll && cnns[iii].namespace_name == ""; if (!is_main_namespace) { //определяем синтетический класс для модуля cur_type = mb.DefineType(cnns[iii].namespace_name + "." + cnns[iii].namespace_name, TypeAttributes.Public); types.Add(cur_type); NamespaceTypesList.Add(cur_type); NamespacesTypes.Add(cnns[iii], cur_type); if (cnns[iii].IsMain) { TypeBuilder attr_class = mb.DefineType(cnns[iii].namespace_name + "." + "$GlobAttr", TypeAttributes.Public | TypeAttributes.BeforeFieldInit, typeof(Attribute)); ConstructorInfo attr_ci = attr_class.DefineDefaultConstructor(MethodAttributes.Public); cur_type.SetCustomAttribute(attr_ci, new byte[4] { 0x01, 0x00, 0x00, 0x00 }); attr_class.CreateType(); } else { TypeBuilder attr_class = mb.DefineType(cnns[iii].namespace_name + "." + "$ClassUnitAttr", TypeAttributes.Public | TypeAttributes.BeforeFieldInit, typeof(Attribute)); ConstructorInfo attr_ci = attr_class.DefineDefaultConstructor(MethodAttributes.Public); cur_type.SetCustomAttribute(attr_ci, new byte[4] { 0x01, 0x00, 0x00, 0x00 }); attr_class.CreateType(); } } else { NamespacesTypes.Add(cnns[iii], entry_type); } } if (comp_opt.target == TargetType.Dll) { for (int iii = 0; iii < cnns.Length; iii++) { string tmp = cur_unit; if (cnns[iii].namespace_name != "") cur_unit = cnns[iii].namespace_name; else cur_unit = entry_cur_unit; foreach (ITemplateClass tc in cnns[iii].templates) { CreateTemplateClass(tc); } cur_unit = tmp; } for (int iii = 0; iii < cnns.Length; iii++) { string tmp = cur_unit; if (cnns[iii].namespace_name != "") cur_unit = cnns[iii].namespace_name; else cur_unit = entry_cur_unit; foreach (ITypeSynonym ts in cnns[iii].type_synonims) { CreateTypeSynonim(ts); } cur_unit = tmp; } } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii].Location == null ? SourceFileName : cnns[iii].Location.document.file_name]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; ConvertTypeMemberHeaders(cnns[iii].types); } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii].Location == null ? SourceFileName : cnns[iii].Location.document.file_name]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; ConvertFunctionHeaders(cnns[iii].functions); } if (p.InitializationCode != null) { tmp_il = il; if (entry_meth != null) { il = entry_meth.GetILGenerator(); ConvertStatement(p.InitializationCode); } il = tmp_il; } //Переводим псевдоинстанции generic-типов foreach (IGenericTypeInstance ictn in p.generic_type_instances) { ConvertGenericInstanceTypeMembers(ictn); } //Переводим псевдоинстанции функций foreach (IGenericFunctionInstance igfi in p.generic_function_instances) { ConvertGenericFunctionInstance(igfi); } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii].Location == null ? SourceFileName : cnns[iii].Location.document.file_name]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; //генерим инциализацию для полей foreach (SemanticTree.ICommonTypeNode ctn in cnns[iii].types) GenerateInitCodeForFields(ctn); } ConstructorBuilder unit_cci = null; //Переводим заголовки всего остального (процедур, переменных) for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii].Location == null ? SourceFileName : cnns[iii].Location.document.file_name]; bool is_main_namespace = iii == cnns.Length - 1 && comp_opt.target != TargetType.Dll; ICommonNamespaceNode cnn = cnns[iii]; string tmp_unit_name = cur_unit; if (!is_main_namespace) cur_unit = cnn.namespace_name; else cur_unit = entry_cur_unit; cur_type = NamespacesTypes[cnn]; //ConvertFunctionHeaders(cnn.functions); if (!is_main_namespace) { //определяем статический конструктор класса для модуля ConstructorBuilder cb = cur_type.DefineConstructor(MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes); il = cb.GetILGenerator(); if (cnn.IsMain) unit_cci = cb; ModulesInitILGenerators.Add(cur_type, il); //переводим глобальные переменные модуля ConvertGlobalVariables(cnn.variables); //перводим константы ConvertNamespaceConstants(cnn.constants); ConvertNamespaceEvents(cnn.events); //il.Emit(OpCodes.Ret); } else { //Не нарвится мне порядок вызова. надо с этим разобраться init_variables_mb = helper.GetMethodBuilder(cnn.functions[cnn.functions.Length-1]);// cur_type.DefineMethod("$InitVariables", MethodAttributes.Public | MethodAttributes.Static); il = entry_meth.GetILGenerator(); ModulesInitILGenerators.Add(cur_type, il); il = init_variables_mb.GetILGenerator(); ConvertGlobalVariables(cnn.variables); il = entry_meth.GetILGenerator(); //перводим константы ConvertNamespaceConstants(cnn.constants); ConvertNamespaceEvents(cnn.events); //il.Emit(OpCodes.Ret); } cur_unit = tmp_unit_name; } if (p.InitializationCode != null) { tmp_il = il; if (entry_meth == null) { il = unit_cci.GetILGenerator(); ConvertStatement(p.InitializationCode); } il = tmp_il; } cur_type = entry_type; //is_in_unit = false; //переводим реализации for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii].Location == null ? SourceFileName : cnns[iii].Location.document.file_name]; bool is_main_namespace = iii == 0 && comp_opt.target != TargetType.Dll; ICommonNamespaceNode cnn = cnns[iii]; string tmp_unit_name = cur_unit; if (!is_main_namespace) cur_unit = cnn.namespace_name; //if (iii > 0) is_in_unit = true; cur_unit_type = NamespacesTypes[cnns[iii]]; cur_type = cur_unit_type; ConvertTypeImplementations(cnn.types); ConvertFunctionsBodies(cnn.functions); cur_unit = tmp_unit_name; } if (comp_opt.target != TargetType.Dll && p.main_function != null) { cur_unit_type = NamespacesTypes[cnns[0]]; cur_type = cur_unit_type; ConvertBody(p.main_function.function_code); } for (int iii = 0; iii < cnns.Length; iii++) { if (save_debug_info) doc = sym_docs[cnns[iii].Location == null ? SourceFileName : cnns[iii].Location.document.file_name]; cur_type = NamespacesTypes[cnns[iii]]; cur_unit_type = NamespacesTypes[cnns[iii]]; //вставляем ret в int_meth foreach (SemanticTree.ICommonTypeNode ctn in cnns[iii].types) GenerateRetForInitMeth(ctn); ModulesInitILGenerators[cur_type].Emit(OpCodes.Ret); } for (int iii = 0; iii < cnns.Length; iii++) { MakeAttribute(cnns[iii]); } doc = first_doc; cur_type = entry_type; CloseTypes();//закрываем типы entry_type.CreateType(); switch (comp_opt.target) { case TargetType.Exe: ab.SetEntryPoint(entry_meth, PEFileKinds.ConsoleApplication); break; case TargetType.WinExe: if (!comp_opt.ForRunningWithEnvironment) ab.SetEntryPoint(entry_meth, PEFileKinds.WindowApplication); else ab.SetEntryPoint(entry_meth, PEFileKinds.ConsoleApplication); break; } /**/ try { //ne osobo vazhnaja vesh, sohranjaet v exe-shnik spisok ispolzuemyh prostranstv imen, dlja strahovki obernuli try catch if (comp_opt.dbg_attrs == DebugAttributes.ForDebbuging) { string[] namespaces = p.UsedNamespaces; TypeBuilder attr_class = mb.DefineType("$UsedNsAttr", TypeAttributes.Public | TypeAttributes.BeforeFieldInit, typeof(Attribute)); FieldBuilder fld_ns = attr_class.DefineField("ns", TypeFactory.StringType, FieldAttributes.Public); FieldBuilder fld_count = attr_class.DefineField("count", TypeFactory.Int32Type, FieldAttributes.Public); ConstructorBuilder attr_ci = attr_class.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[2] { TypeFactory.Int32Type, TypeFactory.StringType }); ILGenerator attr_il = attr_ci.GetILGenerator(); attr_il.Emit(OpCodes.Ldarg_0); attr_il.Emit(OpCodes.Ldarg_1); attr_il.Emit(OpCodes.Stfld, fld_count); attr_il.Emit(OpCodes.Ldarg_0); attr_il.Emit(OpCodes.Ldarg_2); attr_il.Emit(OpCodes.Stfld, fld_ns); attr_il.Emit(OpCodes.Ret); int len = 2 + 2 + 4 + 1; foreach (string ns in namespaces) { len += ns.Length + 1; } byte[] bytes = new byte[len]; bytes[0] = 1; bytes[1] = 0; using (BinaryWriter bw = new BinaryWriter(new MemoryStream())) { bw.Write(namespaces.Length); System.Text.StringBuilder sb = new System.Text.StringBuilder(); foreach (string ns in namespaces) { sb.Append(Convert.ToChar(ns.Length)); sb.Append(ns); //bw.Write(ns); } if (sb.Length > 127) { len += 1; bytes = new byte[len]; bytes[0] = 1; bytes[1] = 0; } bw.Write(sb.ToString()); bw.Seek(0, SeekOrigin.Begin); bw.BaseStream.Read(bytes, 2, len - 4); if (sb.Length > 127) { bytes[7] = (byte)(sb.Length & 0xFF); bytes[6] = (byte)(0x80 | ((sb.Length & 0xFF00) >> 8)); } } entry_type.SetCustomAttribute(attr_ci, bytes); attr_class.CreateType(); } } catch (Exception e) { } if (an.Name == "PABCRtl" || an.Name == "PABCRtl32") { CustomAttributeBuilder cab = new CustomAttributeBuilder(typeof(AssemblyKeyFileAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { an.Name == "PABCRtl" ? "PublicKey.snk" : "PublicKey32.snk" }); ab.SetCustomAttribute(cab); cab = new CustomAttributeBuilder(typeof(AssemblyDelaySignAttribute).GetConstructor(new Type[] { typeof(bool) }), new object[] { true }); ab.SetCustomAttribute(cab); cab = new CustomAttributeBuilder(typeof(TargetFrameworkAttribute).GetConstructor(new Type[] { typeof(string) }), new object[] { ".NETFramework,Version=v4.0" }); ab.SetCustomAttribute(cab); } ab.SetCustomAttribute(new CustomAttributeBuilder(typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) }), new object[] { SecurityRuleSet.Level2 }, new PropertyInfo[] { typeof(SecurityRulesAttribute).GetProperty("SkipVerificationInFullTrust") }, new object[] { true })); if (entry_meth != null && comp_opt.target == TargetType.WinExe) { entry_meth.SetCustomAttribute(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), new byte[] { 0x01, 0x00, 0x00, 0x00 }); } List<FileStream> ResStreams = new List<FileStream>(); if (ResourceFiles != null) foreach (string resname in ResourceFiles) { FileStream stream = File.OpenRead(resname); ResStreams.Add(stream); mb.DefineManifestResource(Path.GetFileName(resname), stream, ResourceAttributes.Public); } ab.SetCustomAttribute(typeof(System.Runtime.CompilerServices.CompilationRelaxationsAttribute).GetConstructor(new Type[1] { TypeFactory.Int32Type }), new byte[] { 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }); if (RunOnly) { object main_class = ab.CreateInstance(cur_unit + ".Program"); MethodInfo methodInfo = main_class.GetType().GetMethod("Main"); methodInfo.Invoke(main_class, null); } else { int tries = 0; bool not_done = true; do { try { if (comp_opt.target == TargetType.Exe || comp_opt.target == TargetType.WinExe) { if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x86) ab.Save(an.Name + ".exe", PortableExecutableKinds.Required32Bit, ImageFileMachine.I386); //else if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x64) // ab.Save(an.Name + ".exe", PortableExecutableKinds.PE32Plus, ImageFileMachine.IA64); else ab.Save(an.Name + ".exe"); //сохраняем сборку } else { if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x86) ab.Save(an.Name + ".dll", PortableExecutableKinds.Required32Bit, ImageFileMachine.I386); //else if (comp_opt.platformtarget == NETGenerator.CompilerOptions.PlatformTarget.x64) // ab.Save(an.Name + ".dll", PortableExecutableKinds.PE32Plus, ImageFileMachine.IA64); else ab.Save(an.Name + ".dll"); } not_done = false; } catch (System.Runtime.InteropServices.COMException e) { throw new TreeConverter.SaveAssemblyError(e.Message); } catch (System.IO.IOException e) { if (tries < num_try_save) tries++; else throw new TreeConverter.SaveAssemblyError(e.Message); } } while (not_done); } foreach (FileStream fs in ResStreams) fs.Close(); } private void AddSpecialInitDebugCode() { //il.Emit(OpCodes.Call,typeof(Console).GetMethod("ReadLine")); //il.Emit(OpCodes.Pop); } private void ConvertNamespaceConstants(INamespaceConstantDefinitionNode[] Constants) { foreach (INamespaceConstantDefinitionNode Constant in Constants) ConvertConstantDefinitionNode(Constant, Constant.name, Constant.type, Constant.constant_value); } private void ConvertNamespaceEvents(ICommonNamespaceEventNode[] Events) { foreach (ICommonNamespaceEventNode Event in Events) Event.visit(this); } private void ConvertCommonFunctionConstantDefinitions(ICommonFunctionConstantDefinitionNode[] Constants) { foreach (ICommonFunctionConstantDefinitionNode Constant in Constants) //ConvertFunctionConstantDefinitionNode(Constant); ConvertConstantDefinitionNode(Constant, Constant.name, Constant.type, Constant.constant_value); } private void ConvertConstantDefinitionNode(IConstantDefinitionNode cnst, string name, ITypeNode type, IConstantNode constant_value) { if (constant_value is IArrayConstantNode) ConvertArrayConstantDef(cnst, name, type, constant_value); else if (constant_value is IRecordConstantNode || constant_value is ICompiledStaticMethodCallNodeAsConstant) ConvertConstantDefWithInitCall(cnst, name, type, constant_value); else if (constant_value is ICommonNamespaceFunctionCallNodeAsConstant || constant_value is IBasicFunctionCallNodeAsConstant || constant_value is ICommonConstructorCallAsConstant || constant_value is ICompiledStaticFieldReferenceNodeAsConstant) ConvertSetConstantDef(cnst, name, type, constant_value); else ConvertSimpleConstant(cnst, name, type, constant_value); } private void ConvertSetConstantDef(IConstantDefinitionNode cnst, string name, ITypeNode type, IConstantNode constant_value) { TypeInfo ti = helper.GetTypeReference(type); FieldAttributes attrs = FieldAttributes.Public | FieldAttributes.Static; if (comp_opt.target == TargetType.Dll) attrs |= FieldAttributes.InitOnly; FieldBuilder fb = cur_type.DefineField(name, ti.tp, attrs); //il.Emit(OpCodes.Newobj, ti.tp.GetConstructor(Type.EmptyTypes)); //il.Emit(OpCodes.Stsfld, fb); if (cnst != null) helper.AddConstant(cnst, fb); bool tmp = save_debug_info; save_debug_info = false; constant_value.visit(this); save_debug_info = tmp; il.Emit(OpCodes.Stsfld, fb); if (!ConvertedConstants.ContainsKey(constant_value)) ConvertedConstants.Add(constant_value, fb); } private void ConvertSimpleConstant(IConstantDefinitionNode cnst, string name, ITypeNode type, IConstantNode constant_value) { FieldBuilder fb = cur_type.DefineField(name, helper.GetTypeReference(type).tp, FieldAttributes.Static | FieldAttributes.Public | FieldAttributes.Literal); Type t = helper.GetTypeReference(type).tp; if (t.IsEnum) { if (!(t is EnumBuilder)) fb.SetConstant(Enum.ToObject(t, (constant_value as IEnumConstNode).constant_value)); else fb.SetConstant(constant_value.value); } else if (!(constant_value is INullConstantNode)) { if (constant_value.value.GetType() != t) { } else fb.SetConstant(constant_value.value); } } private void PushConstantValue(IConstantNode cnst) { if (cnst is IIntConstantNode) PushIntConst((cnst as IIntConstantNode).constant_value); else if (cnst is IDoubleConstantNode) PushDoubleConst((cnst as IDoubleConstantNode).constant_value); else if (cnst is IFloatConstantNode) PushFloatConst((cnst as IFloatConstantNode).constant_value); else if (cnst is ICharConstantNode) PushCharConst((cnst as ICharConstantNode).constant_value); else if (cnst is IStringConstantNode) PushStringConst((cnst as IStringConstantNode).constant_value); else if (cnst is IByteConstantNode) PushByteConst((cnst as IByteConstantNode).constant_value); else if (cnst is ILongConstantNode) PushLongConst((cnst as ILongConstantNode).constant_value); else if (cnst is IBoolConstantNode) PushBoolConst((cnst as IBoolConstantNode).constant_value); else if (cnst is ISByteConstantNode) PushSByteConst((cnst as ISByteConstantNode).constant_value); else if (cnst is IUShortConstantNode) PushUShortConst((cnst as IUShortConstantNode).constant_value); else if (cnst is IUIntConstantNode) PushUIntConst((cnst as IUIntConstantNode).constant_value); else if (cnst is IULongConstantNode) PushULongConst((cnst as IULongConstantNode).constant_value); else if (cnst is IShortConstantNode) PushShortConst((cnst as IShortConstantNode).constant_value); else if (cnst is IEnumConstNode) PushIntConst((cnst as IEnumConstNode).constant_value); else if (cnst is INullConstantNode) il.Emit(OpCodes.Ldnull); } private void ConvertConstantDefWithInitCall(IConstantDefinitionNode cnst, string name, ITypeNode type, IConstantNode constant_value) { TypeInfo ti = helper.GetTypeReference(type); FieldAttributes attrs = FieldAttributes.Public | FieldAttributes.Static; if (comp_opt.target == TargetType.Dll) attrs |= FieldAttributes.InitOnly; FieldBuilder fb = cur_type.DefineField(name, ti.tp, attrs); if (cnst != null) helper.AddConstant(cnst, fb); bool tmp = save_debug_info; save_debug_info = false; AddInitCall(il, fb, ti.init_meth, constant_value); save_debug_info = tmp; if (!ConvertedConstants.ContainsKey(constant_value)) ConvertedConstants.Add(constant_value, fb); } private void ConvertArrayConstantDef(IConstantDefinitionNode cnst, string name, ITypeNode type, IConstantNode constant_value) { //ConvertedConstants.ContainsKey(ArrayConstant) TypeInfo ti = helper.GetTypeReference(type); FieldAttributes attrs = FieldAttributes.Public | FieldAttributes.Static; if (comp_opt.target == TargetType.Dll) attrs |= FieldAttributes.InitOnly; FieldBuilder fb = cur_type.DefineField(name, ti.tp, attrs); if (cnst != null) helper.AddConstant(cnst, fb); CreateArrayGlobalVariable(il, fb, ti, constant_value as IArrayConstantNode, type); if (!ConvertedConstants.ContainsKey(constant_value)) ConvertedConstants.Add(constant_value, fb); } //это требование Reflection.Emit - все типы должны быть закрыты private void CloseTypes() { //(ssyy) TODO: подумать, в каком порядке создавать типы for (int i = 0; i < types.Count; i++) if (types[i].IsInterface) types[i].CreateType(); for (int i = 0; i < enums.Count; i++) enums[i].CreateType(); for (int i = 0; i < value_types.Count; i++) value_types[i].CreateType(); for (int i = 0; i < types.Count; i++) if (!types[i].IsInterface) types[i].CreateType(); } //перевод тела private void ConvertBody(IStatementNode body) { if (!(body is IStatementsListNode) && save_debug_info && body.Location != null) if (body.Location.begin_line_num == 0xFFFFFF) MarkSequencePoint(il, body.Location); body.visit(this); OptMakeExitLabel(); } private void OptMakeExitLabel() { if (ExitProcedureCall) { il.MarkLabel(ExitLabel); ExitProcedureCall = false; } } //перевод заголовков типов private void ConvertTypeHeaders(ICommonTypeNode[] types) { foreach (ICommonTypeNode t in types) { ConvertTypeHeaderInSpecialOrder(t); } } private void CreateTemplateClass(ITemplateClass t) { if (t.serialized_tree != null) { TypeBuilder tb = mb.DefineType(cur_unit + ".%" + t.name, TypeAttributes.Public, TypeFactory.ObjectType); types.Add(tb); CustomAttributeBuilder cust_bldr = new CustomAttributeBuilder(this.TemplateClassAttributeConstructor, new object[1] { t.serialized_tree }); tb.SetCustomAttribute(cust_bldr); } } private void CreateTypeSynonim(ITypeSynonym t) { TypeBuilder tb = mb.DefineType(cur_unit + ".%" + t.name, TypeAttributes.Public, TypeFactory.ObjectType); types.Add(tb); add_possible_type_attribute(tb, t); } private Type CreateTypedFileType(ICommonTypeNode t) { Type tt = helper.GetPascalTypeReference(t); if (tt != null) return tt; TypeBuilder tb = mb.DefineType(cur_unit + ".%" + t.name, TypeAttributes.Public, TypeFactory.ObjectType); types.Add(tb); helper.AddPascalTypeReference(t, tb); add_possible_type_attribute(tb, t); return tb; } private Type CreateTypedSetType(ICommonTypeNode t) { Type tt = helper.GetPascalTypeReference(t); if (tt != null) return tt; TypeBuilder tb = mb.DefineType(cur_unit + ".%" + t.name, TypeAttributes.Public, TypeFactory.ObjectType); types.Add(tb); helper.AddPascalTypeReference(t, tb); add_possible_type_attribute(tb, t); return tb; } private Type CreateShortStringType(ITypeNode t) { TypeBuilder tb = mb.DefineType(cur_unit + ".$string" + (uid++).ToString(), TypeAttributes.Public, TypeFactory.ObjectType); types.Add(tb); add_possible_type_attribute(tb, t); return tb; } //переводим заголовки типов в порядке начиная с базовых классов (т. е. у которых наследники - откомпилированные типы) private void ConvertTypeHeaderInSpecialOrder(ICommonTypeNode t) { if (t.type_special_kind == type_special_kind.diap_type) return; if (t.type_special_kind == type_special_kind.array_kind) return; if (t.depended_from_indefinite) return; if (t.type_special_kind == type_special_kind.typed_file && comp_opt.target == TargetType.Dll) { if (!t.name.Contains(" ")) { CreateTypedFileType(t); return; } } else if (t.type_special_kind == type_special_kind.set_type && comp_opt.target == TargetType.Dll) { if (!t.name.Contains(" ")) { CreateTypedSetType(t); return; } } if (helper.GetTypeReference(t) != null && !t.is_generic_parameter) return; if (t.is_generic_parameter) { //ConvertTypeHeaderInSpecialOrder(t.generic_container); AddTypeWithoutConvert(t); if (converting_generic_param != t) { return; } converting_generic_param = null; } IGenericTypeInstance gti = t as IGenericTypeInstance; if (gti != null) { if (gti.original_generic is ICommonTypeNode) { ConvertTypeHeaderInSpecialOrder((ICommonTypeNode)gti.original_generic); } foreach (ITypeNode itn in gti.generic_parameters) { if (itn is ICommonTypeNode && !itn.is_generic_parameter) { ConvertTypeHeaderInSpecialOrder((ICommonTypeNode)itn); } } } if (t.is_generic_type_definition) { AddTypeWithoutConvert(t); foreach (ICommonTypeNode par in t.generic_params) { converting_generic_param = par; ConvertTypeHeaderInSpecialOrder(par); } } else if ((t.type_special_kind == type_special_kind.none_kind || t.type_special_kind == type_special_kind.record) && !t.IsEnum && !t.is_generic_type_instance && !t.is_generic_parameter) { AddTypeWithoutConvert(t); } foreach (ITypeNode interf in t.ImplementingInterfaces) if (!(interf is ICompiledTypeNode)) ConvertTypeHeaderInSpecialOrder((ICommonTypeNode)interf); if (t.base_type != null && !(t.base_type is ICompiledTypeNode)) { ConvertTypeHeaderInSpecialOrder((ICommonTypeNode)t.base_type); } ConvertTypeHeader(t); } private void AddTypeWithoutConvert(ICommonTypeNode t) { if (helper.GetTypeReference(t) != null) return; TypeBuilder tb = mb.DefineType(cur_unit + "." + t.name, ConvertAttributes(t), null, new Type[0]); helper.AddType(t, tb); //(ssyy) обрабатываем generics if (t.is_generic_type_definition) { int count = t.generic_params.Count; string[] par_names = new string[count]; //Создаём массив имён параметров for (int i = 0; i < count; i++) { par_names[i] = t.generic_params[i].name; } //Определяем параметры в строящемся типе GenericTypeParameterBuilder[] net_pars = tb.DefineGenericParameters(par_names); for (int i = 0; i < count; i++) { //добавляем параметр во внутр. структуры helper.AddExistingType(t.generic_params[i], net_pars[i]); } } } //перевод релизаций типов private void ConvertTypeImplementations(ICommonTypeNode[] types) { foreach (ICommonTypeNode t in types) //если это не особый тип переводим реализацию наверно здесь много лишнего нужно оставить ISimpleArrayNode { if ( t.type_special_kind != type_special_kind.diap_type && !t.depended_from_indefinite) t.visit(this); } } private void ConvertTypeMemberHeaderAndRemoveFromList(ICommonTypeNode type, List<ICommonTypeNode> types) { if (!type.depended_from_indefinite) { if (type.type_special_kind == type_special_kind.array_wrapper && type.element_type.type_special_kind == type_special_kind.array_wrapper && type.element_type is ICommonTypeNode && types.IndexOf((ICommonTypeNode)(type.element_type)) > -1) { ConvertTypeMemberHeaderAndRemoveFromList((ICommonTypeNode)(type.element_type), types); } ConvertTypeMemberHeader(type); } types.Remove(type); } //перевод заголовков членов класса private void ConvertTypeMemberHeaders(ICommonTypeNode[] types) { //(ssyy) Переупорядочиваем, чтобы массивы создавались в правильном порядке List<ICommonTypeNode> ts = new List<ICommonTypeNode>(types); while (ts.Count > 0) { ConvertTypeMemberHeaderAndRemoveFromList(ts[0], ts); } foreach (ICommonTypeNode t in types) { foreach (ICommonMethodNode meth in t.methods) { if (meth.is_generic_function) { ConvertTypeInstancesMembersInFunction(meth); } } } } private Dictionary<TypeBuilder, TypeBuilder> added_types = new Dictionary<TypeBuilder, TypeBuilder>(); private void BuildCloseTypeOrder(ICommonTypeNode value, TypeBuilder tb) { foreach (ICommonClassFieldNode fld in value.fields) { ITypeNode ctn = fld.type; TypeInfo ti = helper.GetTypeReference(ctn); if (ctn is ICommonTypeNode && ti.tp.IsValueType && ti.tp is TypeBuilder) { BuildCloseTypeOrder((ICommonTypeNode)ctn, (TypeBuilder)ti.tp); } } if (!added_types.ContainsKey(tb)) { value_types.Add(tb); added_types[tb] = tb; } } private Type GetTypeOfGenericInstanceField(Type t, FieldInfo finfo) { if (finfo.FieldType.IsGenericParameter) { return t.GetGenericArguments()[finfo.FieldType.GenericParameterPosition]; } else { return finfo.FieldType; } } private void ConvertGenericInstanceTypeMembers(IGenericTypeInstance value) { if (helper.GetTypeReference(value) == null) { return; } ICompiledGenericTypeInstance compiled_inst = value as ICompiledGenericTypeInstance; if (compiled_inst != null) { ConvertCompiledGenericInstanceTypeMembers(compiled_inst); return; } ICommonGenericTypeInstance common_inst = value as ICommonGenericTypeInstance; if (common_inst != null) { ConvertCommonGenericInstanceTypeMembers(common_inst); return; } } //ssyy 04.02.2010. Вернул следующие 2 функции в исходное состояние. private void ConvertCompiledGenericInstanceTypeMembers(ICompiledGenericTypeInstance value) { Type t = helper.GetTypeReference(value).tp; bool is_delegated_type = t.BaseType == TypeFactory.MulticastDelegateType; foreach (IDefinitionNode dn in value.used_members.Keys) { ICompiledConstructorNode iccn = dn as ICompiledConstructorNode; if (iccn != null) { ConstructorInfo ci = TypeBuilder.GetConstructor(t, iccn.constructor_info); helper.AddConstructor(value.used_members[dn] as IFunctionNode, ci); continue; } ICompiledMethodNode icmn = dn as ICompiledMethodNode; if (icmn != null) { if (is_delegated_type && icmn.method_info.IsSpecialName) continue; MethodInfo mi = null; try { mi = TypeBuilder.GetMethod(t, icmn.method_info); } catch { if (icmn.method_info.DeclaringType.IsGenericType && !icmn.method_info.DeclaringType.IsGenericTypeDefinition) { Type gen_def_type = icmn.method_info.DeclaringType.GetGenericTypeDefinition(); foreach (MethodInfo mi2 in gen_def_type.GetMethods()) { if (mi2.MetadataToken == icmn.method_info.MetadataToken) { mi = mi2; break; } } mi = TypeBuilder.GetMethod(t, mi); } else mi = icmn.method_info; } helper.AddMethod(value.used_members[dn] as IFunctionNode, mi); continue; } ICompiledClassFieldNode icfn = dn as ICompiledClassFieldNode; if (icfn != null) { Type ftype = GetTypeOfGenericInstanceField(t, icfn.compiled_field); FieldInfo fi = TypeBuilder.GetField(t, icfn.compiled_field); helper.AddGenericField(value.used_members[dn] as ICommonClassFieldNode, fi, ftype); continue; } } } private void ConvertCommonGenericInstanceTypeMembers(ICommonGenericTypeInstance value) { Type t = helper.GetTypeReference(value).tp; foreach (IDefinitionNode dn in value.used_members.Keys) { ICommonMethodNode icmn = dn as ICommonMethodNode; if (icmn != null) { if (icmn.is_constructor) { MethInfo mi = helper.GetConstructor(icmn); if (mi != null) { ConstructorInfo cnstr = mi.cnstr; ConstructorInfo ci = TypeBuilder.GetConstructor(t, cnstr); helper.AddConstructor(value.used_members[dn] as IFunctionNode, ci); } continue; } else { MethodInfo meth = helper.GetMethod(icmn).mi; if (meth.GetType().FullName == "System.Reflection.Emit.MethodOnTypeBuilderInstantiation") meth = meth.GetGenericMethodDefinition(); MethodInfo mi = TypeBuilder.GetMethod(t, meth); helper.AddMethod(value.used_members[dn] as IFunctionNode, mi); continue; } } ICommonClassFieldNode icfn = dn as ICommonClassFieldNode; if (icfn != null) { FldInfo fldinfo = helper.GetField(icfn); if (!(fldinfo is GenericFldInfo)) { FieldInfo finfo = fldinfo.fi; Type ftype = GetTypeOfGenericInstanceField(t, finfo); FieldInfo fi = TypeBuilder.GetField(t, finfo); helper.AddGenericField(value.used_members[dn] as ICommonClassFieldNode, fi, ftype); } else { FieldInfo finfo = fldinfo.fi; FieldInfo fi = finfo; helper.AddGenericField(value.used_members[dn] as ICommonClassFieldNode, fi, (fldinfo as GenericFldInfo).field_type); } continue; } } } private object[] get_constants(IConstantNode[] cnsts) { object[] objs = new object[cnsts.Length]; for (int i = 0; i < objs.Length; i++) { objs[i] = cnsts[i].value; } return objs; } private PropertyInfo[] get_named_properties(IPropertyNode[] props) { PropertyInfo[] arr = new PropertyInfo[props.Length]; for (int i = 0; i < arr.Length; i++) { if (props[i] is ICompiledPropertyNode) arr[i] = (props[i] as ICompiledPropertyNode).property_info; else arr[i] = helper.GetProperty(props[i]).prop; } return arr; } private FieldInfo[] get_named_fields(IVAriableDefinitionNode[] fields) { FieldInfo[] arr = new FieldInfo[fields.Length]; for (int i = 0; i < arr.Length; i++) { if (fields[i] is ICompiledClassFieldNode) arr[i] = (fields[i] as ICompiledClassFieldNode).compiled_field; else arr[i] = helper.GetField(fields[i] as ICommonClassFieldNode).fi; } return arr; } private void MakeAttribute(ICommonNamespaceNode cnn) { IAttributeNode[] attrs = cnn.Attributes; for (int i = 0; i < attrs.Length; i++) { CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); ab.SetCustomAttribute(cab); } } private void MakeAttribute(ICommonTypeNode ctn) { Type t = helper.GetTypeReference(ctn).tp; IAttributeNode[] attrs = ctn.Attributes; for (int i = 0; i < attrs.Length; i++) { //if (attrs[i].AttributeType == SystemLibrary.SystemLibrary.comimport_type) // continue; CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); if (t is TypeBuilder) (t as TypeBuilder).SetCustomAttribute(cab); else if (t is EnumBuilder) (t as EnumBuilder).SetCustomAttribute(cab); } } private void MakeAttribute(ICommonPropertyNode prop) { PropertyBuilder pb = (PropertyBuilder)helper.GetProperty(prop).prop; IAttributeNode[] attrs = prop.Attributes; for (int i = 0; i < attrs.Length; i++) { CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); pb.SetCustomAttribute(cab); } } private void MakeAttribute(ICommonClassFieldNode fld) { FieldBuilder fb = (FieldBuilder)helper.GetField(fld).fi; IAttributeNode[] attrs = fld.Attributes; for (int i = 0; i < attrs.Length; i++) { CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); fb.SetCustomAttribute(cab); } } private void MakeAttribute(ICommonFunctionNode func) { MethodBuilder mb = helper.GetMethod(func).mi as MethodBuilder; IAttributeNode[] attrs = func.Attributes; for (int i = 0; i < attrs.Length; i++) { CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); mb.SetCustomAttribute(cab); } foreach (IParameterNode pn in func.parameters) { ParamInfo pi = helper.GetParameter(pn); if (pi == null) continue; ParameterBuilder pb = pi.pb; attrs = pn.Attributes; for (int i = 0; i < attrs.Length; i++) { CustomAttributeBuilder cab = new CustomAttributeBuilder ((attrs[i].AttributeConstructor is ICompiledConstructorNode) ? (attrs[i].AttributeConstructor as ICompiledConstructorNode).constructor_info : helper.GetConstructor(attrs[i].AttributeConstructor).cnstr, get_constants(attrs[i].Arguments), get_named_properties(attrs[i].PropertyNames), get_constants(attrs[i].PropertyInitializers), get_named_fields(attrs[i].FieldNames), get_constants(attrs[i].FieldInitializers)); pb.SetCustomAttribute(cab); } } } //определяем заголовки членов класса private void ConvertTypeMemberHeader(ICommonTypeNode value) { //если это оболочка над массивом переводим ее особым образом if (value.type_special_kind == type_special_kind.diap_type || value.type_special_kind == type_special_kind.array_kind) return; if (value.fields.Length == 1 && value.fields[0].type is ISimpleArrayNode) { ConvertArrayWrapperType(value); return; } if (value is ISimpleArrayNode) return; //этот тип уже был переведен, поэтому находим его TypeInfo ti = helper.GetTypeReference(value); //ivan if (ti.tp.IsEnum || !(ti.tp is TypeBuilder)) return; TypeBuilder tb = (TypeBuilder)ti.tp; if (tb.IsValueType) BuildCloseTypeOrder(value, tb); //сохраняем контекст TypeInfo tmp_ti = cur_ti; cur_ti = ti; TypeBuilder tmp = cur_type; cur_type = tb; //(ssyy) Если это интерфейс, то пропускаем следующую хрень if (!value.IsInterface) { //определяем метод $Init$ для выделения памяти, если метод еще не определен (в структурах он опред-ся раньше) MethodBuilder clone_mb = null; MethodBuilder ass_mb = null; if (ti.init_meth != null && tb.IsValueType) { clone_mb = ti.clone_meth as MethodBuilder; ass_mb = ti.assign_meth as MethodBuilder; } foreach (ICommonClassFieldNode fld in value.fields) fld.visit(this); foreach (ICommonMethodNode meth in value.methods) ConvertMethodHeader(meth); foreach (ICommonPropertyNode prop in value.properties) prop.visit(this); foreach (IClassConstantDefinitionNode constant in value.constants) constant.visit(this); foreach (ICommonEventNode evnt in value.events) evnt.visit(this); //(ssyy) 21.05.2008 /*foreach (ICommonMethodNode meth in value.methods) { if (meth.is_generic_function) { ConvertTypeInstancesMembersInFunction(meth); } }*/ //добавляем ритерны в специальные методы //ti.init_meth.GetILGenerator().Emit(OpCodes.Ret); //if (hndl_mb != null) hndl_mb.GetILGenerator().Emit(OpCodes.Ret); if (clone_mb != null) { clone_mb.GetILGenerator().Emit(OpCodes.Ldloc_0); clone_mb.GetILGenerator().Emit(OpCodes.Ret); } if (ass_mb != null) { ass_mb.GetILGenerator().Emit(OpCodes.Ret); } if (ti.fix_meth != null) { ti.fix_meth.GetILGenerator().Emit(OpCodes.Ret); } }