예제 #1
0
        public ProjectConverter(EProjectFile.EProjectFile source, EocProjectType projectType = EocProjectType.Console, string projectNamespace = "e::user", ILoggerWithContext logger = null)
        {
            this.Logger = logger ?? new NullLoggerWithContext();

            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            this.IdToNameMap    = new IdToNameMap(source.Code, source.Resource, source.LosableSection);
            this.ClassIdMap     = source.Code.Classes.ToDictionary(x => x.Id);
            this.MethodIdMap    = source.Code.Methods.ToDictionary(x => x.Id);
            this.DllIdMap       = source.Code.DllDeclares.ToDictionary(x => x.Id);
            this.StructIdMap    = source.Code.Structs.ToDictionary(x => x.Id);
            this.GlobalVarIdMap = source.Code.GlobalVariables.ToDictionary(x => x.Id);
            this.ConstantIdMap  = source.Resource.Constants.ToDictionary(x => x.Id);

            this.ClassVarIdMap      = new Dictionary <int, ClassVariableInfo>();
            this.MethodIdToClassMap = new Dictionary <int, ClassInfo>();
            foreach (var item in source.Code.Classes)
            {
                Array.ForEach(item.Method, x => MethodIdToClassMap.Add(x, item));
                Array.ForEach(item.Variables, x => ClassVarIdMap.Add(x.Id, x));
            }

            projectNamespace       = projectNamespace ?? "e::user";
            this.ProjectNamespace  = projectNamespace;
            this.TypeNamespace     = projectNamespace + "::type";
            this.CmdNamespace      = projectNamespace + "::cmd";
            this.DllNamespace      = projectNamespace + "::dll";
            this.ConstantNamespace = projectNamespace + "::constant";
            this.GlobalNamespace   = projectNamespace + "::global";
            this.Source            = source;
            this.Libs = source.Code.Libraries.Select(
                x =>
            {
                try
                {
                    return(LibInfo.Load(x));
                }
                catch (Exception ex)
                {
                    Logger.Warn("加载fne信息失败,请检查易语言环境,支持库:{0},异常信息:{1}", x.Name, ex);
                    return(null);
                }
            }).ToArray();
            this.EocLibs = source.Code.Libraries.Select(
                x =>
            {
                try
                {
                    return(EocLibInfo.Load(x));
                }
                catch (Exception ex)
                {
                    Logger.Warn("加载eoc库信息失败,请检查eoc环境,支持库:{0},异常信息:{1}", x.Name, ex);
                    return(null);
                }
            }).ToArray();
            this.EocHelperLibId    = Array.FindIndex(source.Code.Libraries, x => x.FileName.ToLower() == "EocHelper".ToLower());
            this.DataTypeId_IntPtr = this.EocHelperLibId == -1 ? -1 : EplSystemId.MakeLibDataTypeId((short)this.EocHelperLibId, 0);
            this.ProjectType       = projectType;

            this.EocConstants       = EocConstant.Translate(this, Source.Resource.Constants);
            this.EocStructs         = EocStruct.Translate(this, Source.Code.Structs);
            this.EocGlobalVariables = EocGlobalVariable.Translate(this, Source.Code.GlobalVariables);
            this.EocDllDeclares     = EocDll.Translate(this, Source.Code.DllDeclares);
            this.EocObjectClasses   = EocObjectClass.Translate(this, Source.Code.Classes.Where(x => EplSystemId.GetType(x.Id) == EplSystemId.Type_Class));
            this.EocStaticClasses   = EocStaticClass.Translate(this, Source.Code.Classes.Where(x => EplSystemId.GetType(x.Id) != EplSystemId.Type_Class));
        }
예제 #2
0
        public void Generate(string dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }
            Directory.CreateDirectory(dest);

            foreach (var eocObjectClass in EocObjectClasses)
            {
                eocObjectClass.ParseCode();
                eocObjectClass.Optimize();
            }

            foreach (var eocStaticClass in EocStaticClasses)
            {
                eocStaticClass.ParseCode();
                eocStaticClass.Optimize();
            }

            //分析依赖图
            Array.ForEach(EocConstants, x => x.AnalyzeDependencies(DependencyGraph));
            Array.ForEach(EocStructs, x => x.AnalyzeDependencies(DependencyGraph));
            Array.ForEach(EocGlobalVariables, x => x.AnalyzeDependencies(DependencyGraph));
            Array.ForEach(EocDllDeclares, x => x.AnalyzeDependencies(DependencyGraph));
            Array.ForEach(EocObjectClasses, x => x.AnalyzeDependencies(DependencyGraph));
            Array.ForEach(EocStaticClasses, x => x.AnalyzeDependencies(DependencyGraph));
            if (Source.InitEcSectionInfo != null)
            {
                DependencyGraph.AddVerticesAndEdgeRange(Source.InitEcSectionInfo.InitMethod.Select(x => new Edge <string>("[Root]", GetCppMethodName(x))));
            }
            if (Source.Code.MainMethod != 0)
            {
                DependencyGraph.AddVerticesAndEdge(new Edge <string>("[Root]", GetCppMethodName(Source.Code.MainMethod)));
            }
            else
            {
                DependencyGraph.AddVerticesAndEdge(new Edge <string>("[Root]", "e::user::cmd::_启动子程序"));
            }

            //生成依赖列表
            this.Dependencies = new HashSet <string>();
            GraphUtils.AnalyzeDependencies(DependencyGraph, "[Root]", this.Dependencies);

            //删除未使用代码
            EocConstants       = EocConstants.Where(x => Dependencies.Contains(x.RefId)).ToArray();
            EocStructs         = EocStructs.Where(x => Dependencies.Contains(x.RefId)).ToArray();
            EocGlobalVariables = EocGlobalVariables.Where(x => Dependencies.Contains(x.RefId)).ToArray();
            EocDllDeclares     = EocDllDeclares.Where(x => Dependencies.Contains(x.RefId)).ToArray();
            EocObjectClasses   = EocObjectClasses.Where(x => Dependencies.Contains(x.RefId)).ToArray();
            Array.ForEach(EocObjectClasses, x => x.RemoveUnusedCode(Dependencies));
            Array.ForEach(EocStaticClasses, x => x.RemoveUnusedCode(Dependencies));
            EocStaticClasses = EocStaticClasses.Where(x => x.Method.Count != 0).ToArray();

            //依赖信息
            File.WriteAllText(Path.Combine(dest, "Dependencies.txt"), string.Join("\r\n", this.Dependencies), Encoding.UTF8);
            File.WriteAllBytes(Path.Combine(dest, "DependencyGraph.gv"), Encoding.UTF8.GetBytes(GraphUtils.WriteGraphvizScript(DependencyGraph, "DependencyGraph")));

            string fileName;

            //常量
            fileName = GetFileNameByNamespace(dest, ConstantNamespace, "h");
            using (var writer = new CodeWriter(fileName))
                EocConstant.Define(this, writer, EocConstants);

            //声明自定义数据类型(结构/对象类)
            fileName = GetFileNameByNamespace(dest, TypeNamespace, "h");
            using (var writer = new CodeWriter(fileName))
            {
                DefineAllTypes(writer);
            }

            //实现 对象类
            foreach (var item in EocObjectClasses)
            {
                fileName = GetFileNameByNamespace(dest, item.CppName, "cpp");
                using (var writer = new CodeWriter(fileName))
                    item.ImplementRawObjectClass(writer);
            }

            //静态类
            foreach (var item in EocStaticClasses)
            {
                fileName = GetFileNameByNamespace(dest, item.CppName, "h");
                using (var writer = new CodeWriter(fileName))
                    item.Define(writer);
                fileName = GetFileNameByNamespace(dest, item.CppName, "cpp");
                using (var writer = new CodeWriter(fileName))
                    item.Implement(writer);
            }

            //全局变量
            fileName = GetFileNameByNamespace(dest, GlobalNamespace, "h");
            using (var writer = new CodeWriter(fileName))
                EocGlobalVariable.Define(this, writer, EocGlobalVariables);
            fileName = GetFileNameByNamespace(dest, GlobalNamespace, "cpp");
            using (var writer = new CodeWriter(fileName))
                EocGlobalVariable.Implement(this, writer, EocGlobalVariables);

            //DLL
            fileName = GetFileNameByNamespace(dest, DllNamespace, "h");
            using (var writer = new CodeWriter(fileName))
                EocDll.Define(this, writer, EocDllDeclares);
            fileName = GetFileNameByNamespace(dest, DllNamespace, "cpp");
            using (var writer = new CodeWriter(fileName))
                EocDll.Implement(this, writer, EocDllDeclares);

            //预编译头
            fileName = GetFileNameByNamespace(dest, "stdafx", "h");
            using (var writer = new CodeWriter(fileName))
                MakeStandardHeader(writer);

            //程序入口
            fileName = GetFileNameByNamespace(dest, "entry", "cpp");
            using (var writer = new CodeWriter(fileName))
                MakeProgramEntry(writer);

            //CMake项目配置文件
            fileName = Path.Combine(dest, "CMakeLists.txt");
            using (var writer = new StreamWriter(File.Create(fileName), Encoding.Default))
                MakeCMakeLists(writer);

            //VSCode配置文件
            fileName = Path.Combine(dest, ".vscode", "settings.json");
            Directory.CreateDirectory(Path.GetDirectoryName(fileName));
            using (var writer = new StreamWriter(File.Create(fileName), Encoding.Default))
                MakeVSCodeSettings(writer);
        }
예제 #3
0
        public ProjectConverter(EProjectFile.EProjectFile source, EocProjectType projectType = EocProjectType.Console, string projectNamespace = "e::user", ILoggerWithContext logger = null)
        {
            this.Logger = logger ?? new NullLoggerWithContext();

            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            this.IdToNameMap = new IdToNameMap(source.Code, source.Resource, source.LosableSection);
            this.MethodIdMap = source.Code.Methods.ToDictionary(x => x.Id);

            this.MethodIdToClassMap = new Dictionary <int, ClassInfo>();
            foreach (var item in source.Code.Classes)
            {
                Array.ForEach(item.Method, x => MethodIdToClassMap.Add(x, item));
            }

            projectNamespace       = projectNamespace ?? "e::user";
            this.ProjectNamespace  = projectNamespace;
            this.TypeNamespace     = projectNamespace + "::type";
            this.CmdNamespace      = projectNamespace + "::cmd";
            this.DllNamespace      = projectNamespace + "::dll";
            this.ConstantNamespace = projectNamespace + "::constant";
            this.GlobalNamespace   = projectNamespace + "::global";
            this.Source            = source;
            this.Libs = source.Code.Libraries.Select(
                x =>
            {
                try
                {
                    return(LibInfo.Load(x));
                }
                catch (Exception ex)
                {
                    Logger.Warn("加载fne信息失败,请检查易语言环境,支持库:{0},异常信息:{1}", x.Name, ex);
                    return(null);
                }
            }).ToArray();
            this.EocLibs = source.Code.Libraries.Select(
                x =>
            {
                try
                {
                    return(EocLibInfo.Load(x));
                }
                catch (Exception ex)
                {
                    Logger.Warn("加载eoc库信息失败,请检查eoc环境,支持库:{0},异常信息:{1}", x.Name, ex);
                    return(null);
                }
            }).ToArray();
            LibCmdToDeclaringTypeMap = Libs.Select(lib => {
                var r = new Dictionary <int, int>();
                for (int i = 0; i < lib?.DataType?.Length; i++)
                {
                    if (lib.DataType[i].Method != null)
                    {
                        Array.ForEach(lib.DataType[i].Method, x => r[x] = i);
                    }
                }
                return(r);
            }).ToList().AsReadOnly();

            this.EocHelperLibId    = Array.FindIndex(source.Code.Libraries, x => x.FileName.ToLower() == "EocHelper".ToLower());
            this.DataTypeId_IntPtr = this.EocHelperLibId == -1 ? -1 : EplSystemId.MakeLibDataTypeId((short)this.EocHelperLibId, 0);
            this.ProjectType       = projectType;

            this.EocConstantMap       = EocConstant.Translate(this, Source.Resource.Constants);
            this.EocStructMap         = EocStruct.Translate(this, Source.Code.Structs);
            this.EocGlobalVariableMap = EocGlobalVariable.Translate(this, Source.Code.GlobalVariables);
            this.EocDllDeclareMap     = EocDll.Translate(this, Source.Code.DllDeclares);
            this.EocObjectClassMap    = EocObjectClass.Translate(this, Source.Code.Classes.Where(x => EplSystemId.GetType(x.Id) == EplSystemId.Type_Class));
            this.EocStaticClassMap    = EocStaticClass.Translate(this, Source.Code.Classes.Where(x => EplSystemId.GetType(x.Id) != EplSystemId.Type_Class));


            this.EocMemberMap =
                this.EocObjectClassMap.Values.SelectMany(x => x.MemberInfoMap)
                .Concat(this.EocStaticClassMap.Values.SelectMany(x => x.MemberInfoMap))
                .Concat(this.EocStructMap.Values.SelectMany(x => x.MemberInfoMap))
                .ToSortedDictionary();

            this.EocMethodMap =
                this.EocObjectClassMap.Values.SelectMany(x => x.Method)
                .Concat(this.EocStaticClassMap.Values.SelectMany(x => x.Method))
                .ToSortedDictionary();

            if (ProjectType == EocProjectType.Dll)
            {
                this.EocDllExportMap = EocDllExport.Translate(this, Source.Code.Methods.Where(x => x.IsStatic && x.Public).Select(x => x.Id));
            }
        }