Skip to content

Commit

Permalink
enhance: reconstruct the type system and the reference system [breaki…
Browse files Browse the repository at this point in the history
…ng change]
  • Loading branch information
ArcticLampyrid committed Jul 6, 2020
1 parent f14af0a commit c3a0909
Show file tree
Hide file tree
Showing 34 changed files with 849 additions and 870 deletions.
98 changes: 70 additions & 28 deletions EplOnCppCore/CodeConverter.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using QIQI.EplOnCpp.Core.Expressions;
using QIQI.EplOnCpp.Core.Statements;
using QIQI.EplOnCpp.Core.Utils;
using QIQI.EProjectFile;
using QuickGraph;
using System;
Expand All @@ -13,31 +14,73 @@ public class CodeConverter
public ProjectConverter P { get; }
public string Name { get; }
public string RefId { get; }
public EocCmdInfo EocCmdInfo { get; }
public EocCmdInfo Info { get; }
public bool IsClassMember { get; }
public EocClass ClassItem { get; }
public MethodInfo MethodItem { get; }
public ILoggerWithContext Logger => P.Logger;
public MethodParameterInfo[] Parameters { get; }
public Dictionary<int, MethodParameterInfo> ParamIdMap { get; }
public Dictionary<int, LocalVariableInfo> LocalIdMap { get; }
public SortedDictionary<int, EocParameterInfo> ParamMap { get; }
public SortedDictionary<int, EocLocalVariableInfo> LocalMap { get; }
public EocStatementBlock StatementBlock { get; set; }

private static EocCmdInfo InferEocCmdInfo(ProjectConverter P, MethodInfo rawInfo)
{
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) =>
{
var dataType = EocDataTypes.Translate(P, x.DataType, x.ArrayParameter);
return new EocParameterInfo()
{
ByRef = x.ByRef || x.ArrayParameter || !EocDataTypes.IsValueType(dataType),
Optional = x.OptionalParameter,
VarArgs = false,
DataType = dataType,
CppName = P.GetUserDefinedName_SimpleCppName(x.Id)
};
}).ToList()
};
}

public CodeConverter(ProjectConverter projectConverter, EocClass classItem, MethodInfo methodItem)
{
this.P = projectConverter;
this.Name = P.GetUserDefinedName_SimpleCppName(methodItem.Id);
this.EocCmdInfo = P.GetEocCmdInfo(methodItem);
this.Info = InferEocCmdInfo(P, methodItem);
this.IsClassMember = classItem is EocObjectClass;
this.ClassItem = classItem;
this.MethodItem = methodItem;
this.Parameters = methodItem.Parameters;
this.ParamIdMap = methodItem.Parameters.ToDictionary(x => x.Id);
this.LocalIdMap = methodItem.Variables.ToDictionary(x => x.Id);
if(IsClassMember)
this.RefId = $"{ClassItem.CppName}|{EocCmdInfo.CppName}";
this.ParamMap = new SortedDictionary<int, EocParameterInfo>();
for (int i = 0; i < Info.Parameters.Count; i++)
{
this.ParamMap.Add(methodItem.Parameters[i].Id, Info.Parameters[i]);
}
this.LocalMap = methodItem.Variables.ToSortedDictionary(x => x.Id, x => new EocLocalVariableInfo()
{
CppName = P.GetUserDefinedName_SimpleCppName(x.Id),
DataType = EocDataTypes.Translate(P, x.DataType, x.UBound),
UBound = x.UBound.ToList()
});
if (IsClassMember)
{
this.RefId = $"{ClassItem.CppName}|{Info.CppName}";
}
else
this.RefId = EocCmdInfo.CppName;
{
this.RefId = Info.CppName;
}
}

public void RemoveUnusedCode(HashSet<string> dependencies)
Expand Down Expand Up @@ -70,44 +113,43 @@ public CodeConverter Optimize()

private void WriteOptionalParameterReader(CodeWriter writer)
{
foreach (var x in Parameters.Where(x => x.OptionalParameter))
foreach (var x in Info.Parameters.Where(x => x.Optional))
{
var name = P.GetUserDefinedName_SimpleCppName(x.Id);
var realValueType = P.GetCppTypeName(x.DataType, x.ArrayParameter);
var nullParameter = P.GetNullParameter(x.DataType, x.ArrayParameter);
var initValue = P.GetInitValue(x.DataType, x.ArrayParameter);
var name = x.CppName;
var nullParameter = EocDataTypes.GetNullParameter(x.DataType);
var initValue = EocDataTypes.GetInitValue(x.DataType);
writer.NewLine();
writer.Write($"bool eoc_isNull_{name} = !{name}.has_value();");
if (x.ByRef || x.ArrayParameter || !P.IsValueType(x.DataType))
if (x.ByRef)
{
writer.NewLine();
if (string.IsNullOrWhiteSpace(nullParameter))
{
writer.Write($"{realValueType} eoc_default_{name};");
writer.Write($"{x.DataType} eoc_default_{name};");
}
else
{
writer.Write($"{realValueType} eoc_default_{name}({nullParameter});");
writer.Write($"{x.DataType} eoc_default_{name}({nullParameter});");
}

writer.NewLine();
writer.Write($"{realValueType}& eoc_value_{name} = eoc_isNull_{name} ? (eoc_default_{name} = {initValue}) : {name}.value().get();");
writer.Write($"{x.DataType}& eoc_value_{name} = eoc_isNull_{name} ? (eoc_default_{name} = {initValue}) : {name}.value().get();");
}
else
{
writer.NewLine();
writer.Write($"{realValueType} eoc_value_{name} = eoc_isNull_{name} ? {initValue} : {name}.value();");
writer.Write($"{x.DataType} eoc_value_{name} = eoc_isNull_{name} ? {initValue} : {name}.value();");
}
}
}

public void AnalyzeDependencies(AdjacencyGraph<string, IEdge<string>> graph)
{
P.AnalyzeDependencies(graph, EocCmdInfo, RefId);
foreach (var x in MethodItem.Variables)
P.AnalyzeDependencies(graph, Info, RefId);
foreach (var x in LocalMap.Values)
{
var varRefId = $"{RefId}|{P.GetUserDefinedName_SimpleCppName(x.Id)}";
P.AnalyzeDependencies(graph, varRefId, P.GetCppTypeName(x));
var varRefId = $"{RefId}|{x.CppName}";
P.AnalyzeDependencies(graph, varRefId, x.DataType);
}
StatementBlock.AnalyzeDependencies(graph);
}
Expand All @@ -130,7 +172,7 @@ internal void DefineItem(CodeWriter writer)
writer.Write(accessModifier);
writer.Write(":");
}
P.DefineMethod(writer, EocCmdInfo, Name, isVirtual);
P.DefineMethod(writer, Info, Name, isVirtual);
}

internal void ImplementItem(CodeWriter writer)
Expand All @@ -142,10 +184,10 @@ internal void ImplementItem(CodeWriter writer)
string classRawName = null;
if (ClassItem is EocObjectClass x)
classRawName = x.RawName;
P.WriteMethodHeader(writer, EocCmdInfo, Name, false, classRawName, false);
P.WriteMethodHeader(writer, Info, Name, false, classRawName, false);
using (writer.NewBlock())
{
P.DefineVariable(writer, null, MethodItem.Variables);
P.DefineVariable(writer, null, LocalMap.Values);
WriteOptionalParameterReader(writer);
StatementBlock.WriteTo(writer);
}
Expand Down
15 changes: 9 additions & 6 deletions EplOnCppCore/EocClass.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using QIQI.EProjectFile;
using QIQI.EplOnCpp.Core.Utils;
using QIQI.EProjectFile;
using QuickGraph;
using System;
using System.Collections.Generic;
Expand All @@ -13,7 +14,8 @@ public abstract class EocClass
public ClassInfo RawInfo { get; }
public string Name { get; }
public string CppName { get; }
public List<CodeConverter> Method { get; }
public SortedDictionary<int, CodeConverter> Method { get; set; }
public SortedDictionary<int, EocMemberInfo> MemberInfoMap { get; set; }

public abstract void AnalyzeDependencies(AdjacencyGraph<string, IEdge<string>> graph);
public abstract void RemoveUnusedCode(HashSet<string> dependencies);
Expand All @@ -31,22 +33,23 @@ public EocClass(ProjectConverter p, ClassInfo rawInfo)
{
CppName = $"{P.CmdNamespace}::{Name}";
}
Method = RawInfo.Method.Select(x => P.MethodIdMap[x]).Select(x => new CodeConverter(P, this, x)).ToList();
Method = RawInfo.Method.Select(x => P.MethodIdMap[x]).ToSortedDictionary(x => x.Id, x => new CodeConverter(P, this, x));
}

public void ParseCode()
{
foreach (var item in Method)
foreach (var item in Method.Values)
{
item.ParseCode();
}
}

public void Optimize()
{
for (int i = 0; i < Method.Count; i++)
var keys = Method.Keys.ToList();
foreach (var id in keys)
{
Method[i] = Method[i].Optimize();
Method[id] = Method[id].Optimize();
}
}
}
Expand Down
77 changes: 67 additions & 10 deletions EplOnCppCore/EocConstant.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using QIQI.EProjectFile;
using QIQI.EplOnCpp.Core.Utils;
using QIQI.EProjectFile;
using QuickGraph;
using System;
using System.Collections.Generic;
Expand All @@ -23,7 +24,7 @@ public EocConstant(ProjectConverter p, string name, EocConstantInfo info)

public void AnalyzeDependencies(AdjacencyGraph<string, IEdge<string>> graph)
{
if(RefId != null)
if (RefId != null)
{
graph.AddVertex(RefId);
P.AnalyzeDependencies(graph, RefId, Info.DataType);
Expand Down Expand Up @@ -113,36 +114,92 @@ private void ImplementItem(CodeWriter writer)
}
}

public static EocConstant[] Translate(ProjectConverter P, IEnumerable<ConstantInfo> constantInfos)
public static SortedDictionary<int, EocConstant> Translate(ProjectConverter P, IEnumerable<ConstantInfo> rawInfos)
{
return constantInfos.Select(x => Translate(P, x)).ToArray();
return rawInfos.ToSortedDictionary(x => x.Id, x => Translate(P, x));
}

public static EocConstant Translate(ProjectConverter P, ConstantInfo constantInfo)
public static EocConstant Translate(ProjectConverter P, ConstantInfo rawInfo)
{
return new EocConstant(P, P.GetUserDefinedName_SimpleCppName(constantInfo.Id), P.GetEocConstantInfo(constantInfo.Id));
var name = P.GetUserDefinedName_SimpleCppName(rawInfo.Id);
var cppName = $"{P.ConstantNamespace}::{name}";
string getter = null;
CppTypeName dataType;
switch (rawInfo.Value)
{
case double v:
if ((int)v == v)
{
dataType = EocDataTypes.Int;
}
else if ((long)v == v)
{
dataType = EocDataTypes.Long;
}
else
{
dataType = EocDataTypes.Double;
}
break;

case bool _:
dataType = EocDataTypes.Bool;
break;

case DateTime _:
dataType = EocDataTypes.DateTime;
break;

case string _:
dataType = EocDataTypes.String;
getter = cppName;
cppName = null;
break;

case byte[] _:
dataType = EocDataTypes.Bin;
getter = cppName;
cppName = null;
break;

case null:
return null;

default:
throw new Exception();
}

var info = new EocConstantInfo()
{
CppName = cppName,
Getter = getter,
DataType = dataType,
Value = rawInfo.Value
};

return new EocConstant(P, name, info);
}

public static void Define(ProjectConverter P, CodeWriter writer, EocConstant[] eocDlls)
public static void Define(ProjectConverter P, CodeWriter writer, SortedDictionary<int, EocConstant> map)
{
writer.Write("#pragma once");
writer.NewLine();
writer.Write("#include <e/system/basic_type.h>");
using (writer.NewNamespace(P.ConstantNamespace))
{
foreach (var item in eocDlls)
foreach (var item in map.Values)
{
item.DefineItem(writer);
}
}
}

public static void Implement(ProjectConverter P, CodeWriter writer, EocConstant[] eocDlls)
public static void Implement(ProjectConverter P, CodeWriter writer, SortedDictionary<int, EocConstant> map)
{
writer.Write("#include \"constant.h\"");
using (writer.NewNamespace(P.ConstantNamespace))
{
foreach (var item in eocDlls)
foreach (var item in map.Values)
{
item.ImplementItem(writer);
}
Expand Down
20 changes: 10 additions & 10 deletions EplOnCppCore/EocConstantInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ public class EocConstantInfo
public string RefId => CppName ?? Getter;
public string CppName { get; set; }
public string Getter { get; set; }
public CppTypeName DataType { get; set; } = ProjectConverter.CppTypeName_Int;
public object Value { get ; set; }
public CppTypeName DataType { get; set; } = EocDataTypes.Int;
public object Value { get; set; }

private static readonly Dictionary<CppTypeName, Func<object, object>> ProcessorForNormalization = new Dictionary<CppTypeName, Func<object, object>> {
{ ProjectConverter.CppTypeName_Bool, x => Convert.ToBoolean(x) },
{ ProjectConverter.CppTypeName_Byte, x => Convert.ToByte(x) },
{ ProjectConverter.CppTypeName_Short, x => Convert.ToInt16(x) },
{ ProjectConverter.CppTypeName_Int, x => Convert.ToInt32(x) },
{ ProjectConverter.CppTypeName_Long, x => Convert.ToInt64(x) },
{ ProjectConverter.CppTypeName_Float, x => Convert.ToSingle(x) },
{ ProjectConverter.CppTypeName_Double, x => Convert.ToDouble(x) },
{ ProjectConverter.CppTypeName_String, x => Convert.ToString(x) }
{ EocDataTypes.Bool, x => Convert.ToBoolean(x) },
{ EocDataTypes.Byte, x => Convert.ToByte(x) },
{ EocDataTypes.Short, x => Convert.ToInt16(x) },
{ EocDataTypes.Int, x => Convert.ToInt32(x) },
{ EocDataTypes.Long, x => Convert.ToInt64(x) },
{ EocDataTypes.Float, x => Convert.ToSingle(x) },
{ EocDataTypes.Double, x => Convert.ToDouble(x) },
{ EocDataTypes.String, x => Convert.ToString(x) }
};

public void Normalize()
Expand Down
Loading

0 comments on commit c3a0909

Please sign in to comment.