public static void DefineStructMarshaler(ProjectConverter P, CodeWriter writer, EocStruct[] collection) { //In e::system var map = collection.ToDictionary(x => x.RawInfo.Id); var graph = new AdjacencyGraph <EocStruct, IEdge <EocStruct> >(); foreach (var item in collection) { var hasDependentItem = false; foreach (var member in item.RawInfo.Member) { if (EplSystemId.GetType(member.DataType) == EplSystemId.Type_Struct && map.TryGetValue(member.DataType, out var memberType)) { graph.AddVerticesAndEdge(new Edge <EocStruct>(memberType, item)); hasDependentItem = true; } } if (!hasDependentItem) { graph.AddVertex(item); } } foreach (var item in graph.TopologicalSort()) { item.DefineStructMarshaler(writer); } }
public static EocVariableExpression Translate(CodeConverter C, VariableExpression expr) { if (expr == null) { return(null); } switch (EplSystemId.GetType(expr.Id)) { case EplSystemId.Type_Local: if (C.ParamIdMap.TryGetValue(expr.Id, out var parameterInfo)) { return(new EocVariableExpression(C, parameterInfo)); } var localVarInfo = C.LocalIdMap[expr.Id]; return(new EocVariableExpression(C, localVarInfo)); case EplSystemId.Type_ClassMember: var classVar = C.P.ClassVarIdMap[expr.Id]; return(new EocVariableExpression(C, classVar)); case EplSystemId.Type_Global: var globalVar = C.P.GlobalVarIdMap[expr.Id]; return(new EocVariableExpression(C, globalVar)); case int x: throw new Exception("未知变量类型:0x" + x.ToString("X8")); } }
public override void ToTextCode(IdToNameMap nameMap, StringBuilder result, int indent = 0) { if (Target is VariableExpression varExpr && EplSystemId.GetType(varExpr.Id) == EplSystemId.Type_FormSelf) { // 在窗口程序集直接访问窗口系统属性的情况 // Do nothing }
public EocCmdInfo GetEocCmdInfo(int id) { switch (EplSystemId.GetType(id)) { case EplSystemId.Type_Method: return(GetEocCmdInfo(MethodIdMap[id])); case EplSystemId.Type_Dll: return(GetEocCmdInfo(DllIdMap[id])); default: throw new Exception(); } }
public EocCmdInfo GetEocCmdInfo(int id) { switch (EplSystemId.GetType(id)) { case EplSystemId.Type_Method: return(EocMethodMap[id].Info); case EplSystemId.Type_Dll: return(EocDllDeclareMap[id].Info); default: throw new Exception(); } }
public EocClass(ProjectConverter p, ClassInfo rawInfo) { P = p ?? throw new ArgumentNullException(nameof(p)); RawInfo = rawInfo ?? throw new ArgumentNullException(nameof(rawInfo)); Name = P.GetUserDefinedName_SimpleCppName(RawInfo.Id); if (EplSystemId.GetType(rawInfo.Id) == EplSystemId.Type_Class) { CppName = $"{P.TypeNamespace}::{Name}"; } else { CppName = $"{P.CmdNamespace}::{Name}"; } Method = RawInfo.Method.Select(x => P.MethodIdMap[x]).Select(x => new CodeConverter(P, this, x)).ToList(); }
public static CppTypeName Translate(ProjectConverter P, int id, bool isArray = false) { id = NormalizeDataTypeId(P, id); if (id == P.DataTypeId_IntPtr) { return(IntPtr); } if (!BasicTypeMap.TryGetValue(id, out var result)) { if (EplSystemId.GetType(id) == EplSystemId.Type_Class || EplSystemId.GetType(id) == EplSystemId.Type_Struct) { result = new CppTypeName(false, P.TypeNamespace + "::" + P.GetUserDefinedName_SimpleCppName(id)); } else { EplSystemId.DecomposeLibDataTypeId(id, out var libId, out var typeId); if (P.Libs[libId] == null) { return(ErrorType); } if (typeId >= P.Libs[libId].DataType.Length) { return(ErrorType); } var name = P.Libs[libId].DataType[typeId].Name; if (P.EocLibs[libId] == null) { return(ErrorType); } if (!P.EocLibs[libId].Type.ContainsKey(name)) { return(ErrorType); } result = P.EocLibs[libId].Type[name].CppName; } } if (isArray) { result = new CppTypeName(false, "e::system::array", new[] { result }); } return(result); }
public CppTypeName GetCppTypeName(int id, bool isArray = false) { id = TranslateDataTypeId(id); if (id == DataTypeId_IntPtr) { return(CppTypeName_IntPtr); } if (!BasicCppTypeNameMap.TryGetValue(id, out var result)) { if (EplSystemId.GetType(id) == EplSystemId.Type_Class || EplSystemId.GetType(id) == EplSystemId.Type_Struct) { result = new CppTypeName(false, TypeNamespace + "::" + GetUserDefinedName_SimpleCppName(id)); } else { EplSystemId.DecomposeLibDataTypeId(id, out var libId, out var typeId); if (Libs[libId] == null) { return(EocErrorType); } if (typeId >= Libs[libId].DataType.Length) { return(EocErrorType); } var name = Libs[libId].DataType[typeId].Name; if (EocLibs[libId] == null) { return(EocErrorType); } if (!EocLibs[libId].Type.ContainsKey(name)) { return(EocErrorType); } result = EocLibs[libId].Type[name].CppName; } } if (isArray) { result = new CppTypeName(false, "e::system::array", new[] { result }); } return(result); }
public string GetCppMethodName(int id) { switch (EplSystemId.GetType(id)) { case EplSystemId.Type_Method: if (EplSystemId.GetType(MethodIdToClassMap[id].Id) == EplSystemId.Type_Class) { return(GetUserDefinedName_SimpleCppName(id)); } else { return(CmdNamespace + "::" + GetUserDefinedName_SimpleCppName(id)); } case EplSystemId.Type_Dll: return(DllNamespace + "::" + GetUserDefinedName_SimpleCppName(id)); default: throw new Exception(); } }
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)); }
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)); } }
public override void ToTextCode(IdToNameMap nameMap, StringBuilder result, int indent = 0) { if (Target != null) { Target.ToTextCode(nameMap, result, indent); result.Append("."); } if (InvokeSpecial && LibraryId == -2) { if (nameMap.MethodIdToClassId.TryGetValue(MethodId, out var classId) && EplSystemId.GetType(classId) == EplSystemId.Type_Class) { result.Append(nameMap.GetUserDefinedName(classId)); result.Append("."); } } result.Append(LibraryId == -2 || LibraryId == -3 ? nameMap.GetUserDefinedName(MethodId) : nameMap.GetLibCmdName(LibraryId, MethodId)); result.Append(" "); ParamList.ToTextCode(nameMap, result, indent); }
private static EocCmdInfo InferEocCmdInfo(ProjectConverter P, MethodInfo rawInfo, StatementBlock rawStatementBlock) { var autoParam = new HashSet <int>(); for (int i = 0; i < rawStatementBlock.Count;) { if (rawStatementBlock[i] is ExpressionStatement exprStat) { var callExpr = exprStat.Expression; if (callExpr != null && callExpr.LibraryId == P.EocHelperLibId) { var cmdName = P.IdToNameMap.GetLibCmdName(callExpr.LibraryId, callExpr.MethodId); switch (cmdName) { case "EOC标记_自适应参数": if (callExpr.ParamList.FirstOrDefault() is VariableExpression varExpr) { autoParam.Add(varExpr.Id); } rawStatementBlock.RemoveAt(i); continue; } } } i++; } var name = P.GetUserDefinedName_SimpleCppName(rawInfo.Id); string cppName; if (EplSystemId.GetType(P.MethodIdToClassMap[rawInfo.Id].Id) == EplSystemId.Type_Class) { cppName = name; } else { cppName = $"{P.CmdNamespace}::{name}"; } return(new EocCmdInfo() { ReturnDataType = rawInfo.ReturnDataType == 0 ? null : EocDataTypes.Translate(P, rawInfo.ReturnDataType), CppName = cppName, Parameters = rawInfo.Parameters.Select((x) => { CppTypeName dataType; if (autoParam.Contains(x.Id)) { dataType = x.ArrayParameter ? EocDataTypes.ArrayOf(EocDataTypes.Auto) : EocDataTypes.Auto; } else { dataType = EocDataTypes.Translate(P, x.DataType, x.ArrayParameter); } if (dataType == EocDataTypes.Any && !x.ByRef) { //考虑到可空、参考(非基本类型强制参考、基本类型非参考)等问题,实现起来过于麻烦,暂时搁置 throw new NotImplementedException("暂不支持非参考自适应参数,请勾选 参考 或 贡献代码实现相应功能"); } return new EocParameterInfo() { ByRef = x.ByRef || x.ArrayParameter || (!EocDataTypes.IsValueType(dataType) && dataType != EocDataTypes.Any), Optional = x.OptionalParameter, VarArgs = false, DataType = dataType, CppName = P.GetUserDefinedName_SimpleCppName(x.Id) }; }).ToList() }); }