From f5645a06debf87c19c721734d163e93956363f7e Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Wed, 28 Jan 2026 12:00:40 +0800 Subject: [PATCH] refactor: finish refactor ExpFctsAnalyzer in BMapBinder --- .../ExpFctsAnalyzer/CSharpWriter.java | 286 ------------------ .../ExpFctsAnalyzer/CommonHelper.java | 37 +-- .../ExpFctsAnalyzer/ExpFctDecl.java | 29 -- .../ExpFctsAnalyzer/ExpFctParamDecl.java | 48 --- .../ExpFctsAnalyzer/ExpFctsHelper.java | 248 +++++++++++++++ .../ExpFctsAnalyzer/ExpFctsWalker.java | 74 +++-- .../ExpFctsAnalyzer/IndentHelper.java | 42 --- .../ExpFctsAnalyzer/JsonWriter.java | 55 ++-- .../ExpFctsAnalyzer/MainRunner.java | 12 +- .../ExpFctsAnalyzer/PythonWriter.java | 96 ------ .../ExpFctsAnalyzer/VariableType.java | 153 ---------- .../EnumsAnalyzer/JsonWriter.java | 2 +- COMPILE.md | 4 +- 13 files changed, 340 insertions(+), 746 deletions(-) delete mode 100644 Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CSharpWriter.java delete mode 100644 Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctDecl.java delete mode 100644 Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctParamDecl.java create mode 100644 Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsHelper.java delete mode 100644 Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/IndentHelper.java delete mode 100644 Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/PythonWriter.java delete mode 100644 Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/VariableType.java diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CSharpWriter.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CSharpWriter.java deleted file mode 100644 index 8a1e138..0000000 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CSharpWriter.java +++ /dev/null @@ -1,286 +0,0 @@ -import java.io.OutputStreamWriter; -import java.util.Vector; -import java.util.stream.Collectors; - -public class CSharpWriter { - - /** - * The class represent the C# type corresponding to extracted variable type. - */ - private static class CsInteropType { - public CsInteropType() { - mMarshalAs = null; - mCsType = null; - } - - /** - * The argument of MarshalAsAttribute constructor. In generation, this field - * should be used like this: "[MarshalAs(THIS)]" (for parameter) or "[return: - * MarshalAs(THIS)]" (for return value). - */ - public String mMarshalAs; - /** - * The C# type used in interop function declaration for corresponding parameter. - */ - public String mCsType; - } - - /** - * C# specified function which get C# used interop MarshalAs constructor - * arguments and C# type used in interop function declaration. - * - * @param vt The instance of {@linkplain VariableType} for fetching interop - * type. - * @return The corresponding interop type of given variable type. - */ - private static CsInteropType getCsInteropType(ExpFctParamDecl paramdecl) { - // get essential variable type properties first - VariableType vt = paramdecl.mVarType; - String vt_base_type = vt.getBaseType(); - int vt_pointer_level = vt.getPointerLevel(); - - // create return value - CsInteropType ret = new CsInteropType(); - - // use "switch" to check variable type - switch (vt_base_type) { - case "CKSTRING": - // decide direction cookies - String direction_cookie = ""; - if (paramdecl.mIsInput) { - direction_cookie = "In"; - } else { - direction_cookie = "Out"; - } - // only allow 0 and 1 pointer level for string. - switch (vt_pointer_level) { - case 0: - ret.mMarshalAs = "UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringMarshaler), MarshalCookie = \"" + direction_cookie + "\""; - // ret.mMarshalAs = "UnmanagedType.LPUTF8Str"; - ret.mCsType = "string"; - break; - case 1: - ret.mMarshalAs = "UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMarshaler), MarshalCookie = \"" + direction_cookie + "\""; - ret.mCsType = "string[]"; - break; - } - break; - case "CKDWORD": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.U4"; - ret.mCsType = "uint"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "CKWORD": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.U2"; - ret.mCsType = "ushort"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "CKINT": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.I4"; - ret.mCsType = "int"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "bool": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.U1"; - ret.mCsType = "bool"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "CKFLOAT": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.R4"; - ret.mCsType = "float"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "CKBYTE": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.U1"; - ret.mCsType = "byte"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "CK_ID": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.U4"; - ret.mCsType = "uint"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "NakedOutputCallback": - // callback actually is a function pointer - // so it only allow base type without any pointer level. - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.FunctionPtr"; - ret.mCsType = "OutputCallback"; - } - break; - case "BMFile": - // In any case, BMFile only should be raw pointer - if (vt_pointer_level != 0) { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "BMMeshTransition": - // In any case, BMMeshTransition only should be raw pointer - if (vt_pointer_level != 0) { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "VxVector3": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.Struct"; - ret.mCsType = "VxVector3"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "VxVector2": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.Struct"; - ret.mCsType = "VxVector2"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "VxColor": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.Struct"; - ret.mCsType = "VxColor"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "VxMatrix": - if (vt_pointer_level == 0) { - ret.mMarshalAs = "UnmanagedType.Struct"; - ret.mCsType = "VxMatrix"; - } else { - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - case "CK_TEXTURE_SAVEOPTIONS": - case "VX_PIXELFORMAT": - case "VXLIGHT_TYPE": - case "VXTEXTURE_BLENDMODE": - case "VXTEXTURE_FILTERMODE": - case "VXTEXTURE_ADDRESSMODE": - case "VXBLEND_MODE": - case "VXFILL_MODE": - case "VXSHADE_MODE": - case "VXCMPFUNC": - case "VXMESH_LITMODE": - // all enum type use the same strategy - if (vt_pointer_level == 0) { - // all enum type should be marshaled as its underlying type - // but we can use its name in C# directly. - ret.mMarshalAs = "UnmanagedType.U4"; - ret.mCsType = vt_base_type; - } else { - // for pointer type, use IntPtr instead. - ret.mMarshalAs = "UnmanagedType.SysInt"; - ret.mCsType = "IntPtr"; - } - break; - } - - // check whether we successfully get result - if (ret.mMarshalAs == null || ret.mCsType == null) { - throw new IllegalArgumentException("Unexpected type: " + vt.toCType()); - } - - // return value - return ret; - } - - public static void writeCSharpCode(Vector data) throws Exception { - OutputStreamWriter writer = CommonHelper.openWriter("dest/BMExports.cs"); - IndentHelper helper = new IndentHelper(writer); - - // write function decls - for (ExpFctDecl fctdecl : data) { - // write annotation - // summary (just plain function name) - helper.printf("/// %s", fctdecl.mFctName); - // parameter list - for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) { - helper.printf("/// Type: %s. %s%s", paramdecl.mVarName, - paramdecl.mVarType.toCType(), (paramdecl.mIsInput ? "" : "This is OUT parameter. "), - paramdecl.mVarDesc); - } - // return value - helper.puts("/// True if no error, otherwise False."); - - // write real function declaration - // first, write DllImportAttribute - helper.printf( - "[DllImport(g_DllName, EntryPoint = \"%s\", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]", - fctdecl.mFctName); - // second, write return value MarshalAsAttribute - helper.printf("[return: MarshalAs(UnmanagedType.U1)]"); - // then, before we write function body, we need origanize its parameter list - // first - Vector cs_param_list = new Vector(); - for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) { - // create string builder - StringBuilder sb = new StringBuilder(); - // push in out symbol - if (paramdecl.mIsInput) { - sb.append("[In, "); - } else { - sb.append("[Out, "); - } - // get interop type now - CsInteropType interop_type = getCsInteropType(paramdecl); - // push MarshalAsAttribute - sb.append("MarshalAs("); - sb.append(interop_type.mMarshalAs); - sb.append(")] "); - // push out keyword if parameter is out parameter - if (!paramdecl.mIsInput) { - sb.append("out "); - } - // push parameter cs type - sb.append(interop_type.mCsType); - sb.append(" "); - // push parameter name - sb.append(paramdecl.mVarName); - // insert built string into list - cs_param_list.add(sb.toString()); - } - // join built parameter list and output real function declaration - helper.printf("internal static extern bool %s(%s);", fctdecl.mFctName, - cs_param_list.stream().collect(Collectors.joining(", "))); - } - - writer.close(); - } - -} diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CommonHelper.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CommonHelper.java index a8972a8..69d5902 100644 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CommonHelper.java +++ b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/CommonHelper.java @@ -3,29 +3,32 @@ import java.io.FileOutputStream; //import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.nio.charset.StandardCharsets; +import java.nio.file.Path; +import java.nio.file.Paths; public class CommonHelper { -// public static InputStreamReader openReader(String filename) throws Exception { -// FileInputStream fs = new FileInputStream(filename); -// return new InputStreamReader(fs, StandardCharsets.UTF_8); -// } + // =========== File Operations =========== - public static OutputStreamWriter openWriter(String filename) throws Exception { - FileOutputStream fs = new FileOutputStream(filename); - return new OutputStreamWriter(fs, StandardCharsets.UTF_8); + private static Path getRootDirectoryPath() throws Exception { + String rootDir = System.getenv("BMAP_BINDER_ROOT"); + if (rootDir == null) { + throw new RuntimeException("Can not find essential environment variable BMAP_BINDER_ROOT"); + } else { + return Paths.get(rootDir); + } } -// public static void writeSnippet(OutputStreamWriter writer, String snippet_path) throws Exception { -// // open snippet -// InputStreamReader reader = openReader(snippet_path); -// // write into writer -// reader.transferTo(writer); -// reader.close(); -// } - - public static String getDoxygenInOutStr(boolean isInput) { - return isInput ? "in" : "out"; + public static String getInputFilePath(String filename) throws Exception { + Path rootDir = getRootDirectoryPath(); + Path filePath = rootDir.resolve("Extracted").resolve(filename); + return filePath.toString(); + } + + public static String getOutputFilePath(String filename) throws Exception { + Path rootDir = getRootDirectoryPath(); + Path filePath = rootDir.resolve("Analyzed").resolve(filename); + return filePath.toString(); } } diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctDecl.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctDecl.java deleted file mode 100644 index 6f8256b..0000000 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctDecl.java +++ /dev/null @@ -1,29 +0,0 @@ -import java.util.Vector; - -/** - * The class represent an export BMap function. - */ -public class ExpFctDecl { - - /** - * The name of this function. - */ - public String mFctName; - /** - * The return value type of this function. - */ - public VariableType mFctRetType; - /** - * The parameters (arguments) list of this function. Each items are - * {@linkplain ExpFctParamDecl} and represent parameter one by one from left to - * right. - */ - public Vector mFctParams; - - public ExpFctDecl() { - mFctName = ""; - mFctRetType = new VariableType(); - mFctParams = new Vector(); - } - -} diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctParamDecl.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctParamDecl.java deleted file mode 100644 index 3a868db..0000000 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctParamDecl.java +++ /dev/null @@ -1,48 +0,0 @@ - -/** - * The class represent a single parameter (argument) of function. This class - * usually is the member of {@linkplain ExpFctDecl}. - */ -public class ExpFctParamDecl { - - /** - * The type of this parameter. - */ - public VariableType mVarType; - /** - * The name of this parameter. - */ - public String mVarName; - /** - * True if this paramter is marked as input parameter, otherwise false. - *

- * Input parameter and output paramter is commonly used in C/C++ code. By using - * this feature, each function can receive multiple arguments and return - * multiple arguments without defining a struct to hold it. - *

- * The type of input parameter is itself. However, the type of output parameter - * is the pointer of itself. So you may need get its pointer type when - * processing output paramter, especially for the scenario that the target - * language do not support explicit output parameter keyword. - */ - public boolean mIsInput; - /** - * The description of this parameter. - *

- * This description is generated by this program. It will indicate the - * underlying C++ type to tell end user how to treat this paramter because some - * target languages' native calling style can not represent these detail. - *

- * In this program, this field must be written as a annotation of corresponding - * function. - */ - public String mVarDesc; - - public ExpFctParamDecl() { - mVarType = new VariableType(); - mVarName = ""; - mVarDesc = ""; - mIsInput = true; - } - -} diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsHelper.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsHelper.java new file mode 100644 index 0000000..40b7c7c --- /dev/null +++ b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsHelper.java @@ -0,0 +1,248 @@ +import java.util.Collections; +import java.util.Vector; +import java.util.stream.Collectors; + +public class ExpFctsHelper { + + /** + * The class represent the type of each parameters and function return value. + */ + public static class VariableType { + /** + * The base type of this variable removing all ending stars (remove all pointer levels). + * Each item in this Vector is a part of namespace and the last one must be the type itself + * (without any namespace constraint). + * If no namespace constraint for this type, this Vector will only have one item. + *

+ * For end user, it is enough that knowing the last item is type itself. + */ + private Vector mBaseType; + /** + * The pointer level of this type. It is equal to the count of trailing star of + * this field in C style representation. + */ + private int mPointerLevel; + + /** + * Construct an empty varible type. This is commonly used constructor. + */ + public VariableType() { + mBaseType = new Vector(); + mPointerLevel = 0; + } + + /** + * The constructor used for cloning self. This constructor is only can be used + * by self. + * + * @param base_type The hierarchy of the variable type. + * @param pointer_level The pointer level of new created variable type. + */ + private VariableType(Vector base_type, int pointer_level) { + mBaseType = (Vector) base_type.clone(); + mPointerLevel = pointer_level; + } + + /** + * Set this variable type with a type string in C/C++ style. For example + * "NSTest::NSTest2::MyType**". + * + * @param ctype The type string in C/C++ style. + */ + public void fromCType(String ctype) { + if (ctype.isEmpty()) + throw new IllegalArgumentException("empty string can not be parsed."); + + // get pointer part and name part + int len = ctype.length(); + int star_pos = ctype.indexOf('*'); + String namepart; + if (star_pos == -1) { + // no star + namepart = ctype; + mPointerLevel = 0; + } else { + // has star + if (star_pos == 0) + throw new IllegalArgumentException("base type not found."); + namepart = ctype.substring(0, star_pos); + mPointerLevel = len - star_pos; + } + + // resolve name part + mBaseType.clear(); + for (String item : namepart.split("::")) { + mBaseType.add(item); + } + } + + /** + * Build a type string represented by this variable type in C/C++ style. + * + * @return The type string in C/C++ style. + */ + public String toCType() { + return mBaseType.stream().collect(Collectors.joining("::")) + + String.join("", Collections.nCopies(mPointerLevel, "*")); + } + + /** + * Get the base type of this variable type without any namespace. It just simply + * get the last entry in type hierarchy. + * + * @return The base type string without namespace prefix. + */ + public String getBaseType() { + return mBaseType.lastElement(); + } + + /** + * Check whether this variable type is a pointer. This function just check + * whether the pointer level of this variavle type is zero. + * + * @return True if it is pointer, otherwise false. + */ + public boolean isPointer() { + return mPointerLevel != 0; + } + + /** + * Return the pointer level of this variable type. You can simply assume the + * pointer level is equal to the count of trailing star. + * + * @return The pointer level integer. Zero means that this type is not a + * pointer. + */ + public int getPointerLevel() { + return mPointerLevel; + } + + /** + * Return the clone of the type hierarchy of this variable type. + *

+ * It is rarely used. This only should be used when you need the namespace + * hierarchy of this variable type. + * + * @return The clone of current variable type hierarchy. + */ + public Vector getBaseTypeHierarchy() { + return (Vector) mBaseType.clone(); + } + + /** + * Check whether this type is a valid one. It actually check whether type + * hierarchy include at least one entry. + * + * @return True if no problem of this type, otherwise false. + */ + public boolean isValid() { + return mBaseType.size() != 0; + } + + /** + * Return a new created variable type which is the pointer of this variable + * type. + *

+ * In internal implementation, it just create a clone of current variable type + * with the increase of pointer level by 1. + * + * @return The new created pointer type of this variable type. + */ + public VariableType getPointerOfThis() { + return new VariableType(mBaseType, mPointerLevel + 1); + } + + } + + + /** + * The class represent a single parameter (argument) of function. This class + * usually is the member of {@linkplain ExpFct}. + */ + public static class ExpFctParam { + + /** + * The type of this parameter. + */ + public VariableType mVarType; + /** + * The name of this parameter. + */ + public String mVarName; + /** + * True if this paramter is marked as input parameter, otherwise false. + *

+ * Input parameter and output paramter is commonly used in C/C++ code. By using + * this feature, each function can receive multiple arguments and return + * multiple arguments without defining a struct to hold it. + *

+ * The type of input parameter is itself. However, the type of output parameter + * is the pointer of itself. So you may need get its pointer type when + * processing output paramter, especially for the scenario that the target + * language do not support explicit output parameter keyword. + */ + public boolean mIsInput; + /** + * The description of this parameter. + *

+ * This description is generated by this program. It will indicate the + * underlying C++ type to tell end user how to treat this paramter because some + * target languages' native calling style can not represent these detail. + *

+ * In this program, this field must be written as a annotation of corresponding + * function. + */ + public String mVarDesc; + + public ExpFctParam() { + mVarType = new VariableType(); + mVarName = ""; + mVarDesc = ""; + mIsInput = true; + } + + } + + /** + * The class represent an export BMap function. + */ + public static class ExpFct { + + /** + * The name of this function. + */ + public String mFctName; + /** + * The return value type of this function. + */ + public VariableType mFctRetType; + /** + * The parameters (arguments) list of this function. Each items are + * {@linkplain ExpFctParam} and represent parameter one by one from left to + * right. + */ + public Vector mFctParams; + + public ExpFct() { + mFctName = ""; + mFctRetType = new VariableType(); + mFctParams = new Vector(); + } + + } + + /** + * The class represent a collection of export BMap functions. + */ + public static class ExpFctCollection { + /** + * The collection of exported BMap functions. + */ + public Vector mFcts; + + public ExpFctCollection() { + mFcts = new Vector(); + } + } + +} diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsWalker.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsWalker.java index f3b9974..bbfc09d 100644 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsWalker.java +++ b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/ExpFctsWalker.java @@ -1,34 +1,30 @@ import java.util.Collections; -import java.util.Vector; import java.util.stream.Collectors; -import org.antlr.v4.runtime.*; -import org.antlr.v4.runtime.tree.*; - public class ExpFctsWalker extends ExpFctsParserBaseListener { public ExpFctsWalker() { - mFctList = new Vector(); + mFctCollection = null; mCurrentFct = null; mCurrentParam = null; } - public Vector getResult() { - return mFctList; + public ExpFctsHelper.ExpFctCollection getResult() { + return mFctCollection; } - private Vector mFctList; - private ExpFctDecl mCurrentFct; - private ExpFctParamDecl mCurrentParam; + private ExpFctsHelper.ExpFctCollection mFctCollection; + private ExpFctsHelper.ExpFct mCurrentFct; + private ExpFctsHelper.ExpFctParam mCurrentParam; @Override public void enterProgram(ExpFctsParser.ProgramContext ctx) { - mFctList.clear(); + mFctCollection = new ExpFctsHelper.ExpFctCollection(); } @Override public void enterFctDecl(ExpFctsParser.FctDeclContext ctx) { - mCurrentFct = new ExpFctDecl(); + mCurrentFct = new ExpFctsHelper.ExpFct(); } @Override @@ -41,50 +37,50 @@ public class ExpFctsWalker extends ExpFctsParserBaseListener { throw new IllegalArgumentException("invalid interface function return type. must be bool."); // add into list - mFctList.add(mCurrentFct); + mFctCollection.mFcts.add(mCurrentFct); mCurrentFct = null; } @Override public void exitFctArgFileDecl(ExpFctsParser.FctArgFileDeclContext ctx) { - ExpFctParamDecl decl = new ExpFctParamDecl(); - decl.mVarName = ctx.EXPFCTS_IDENTIFIER().getText(); - decl.mVarDesc = "The pointer to corresponding BMFile."; - decl.mIsInput = true; - decl.mVarType.fromCType("BMap::BMFile*"); - mCurrentFct.mFctParams.add(decl); + ExpFctsHelper.ExpFctParam param = new ExpFctsHelper.ExpFctParam(); + param.mVarName = ctx.EXPFCTS_IDENTIFIER().getText(); + param.mVarDesc = "The pointer to corresponding BMFile."; + param.mIsInput = true; + param.mVarType.fromCType("BMap::BMFile*"); + mCurrentFct.mFctParams.add(param); } @Override public void exitFctArgMeshTransDecl(ExpFctsParser.FctArgMeshTransDeclContext ctx) { - ExpFctParamDecl decl = new ExpFctParamDecl(); - decl.mVarName = ctx.EXPFCTS_IDENTIFIER().getText(); - decl.mVarDesc = "The pointer to corresponding BMMeshTransition."; - decl.mIsInput = true; - decl.mVarType.fromCType("BMap::BMMeshTransition*"); - mCurrentFct.mFctParams.add(decl); + ExpFctsHelper.ExpFctParam param = new ExpFctsHelper.ExpFctParam(); + param.mVarName = ctx.EXPFCTS_IDENTIFIER().getText(); + param.mVarDesc = "The pointer to corresponding BMMeshTransition."; + param.mIsInput = true; + param.mVarType.fromCType("BMap::BMMeshTransition*"); + mCurrentFct.mFctParams.add(param); } @Override public void exitFctArgObjDecl(ExpFctsParser.FctArgObjDeclContext ctx) { - ExpFctParamDecl first_decl = new ExpFctParamDecl(); - first_decl.mVarName = ctx.EXPFCTS_IDENTIFIER(0).getText(); - first_decl.mVarDesc = "The pointer to corresponding BMFile."; - first_decl.mIsInput = true; - first_decl.mVarType.fromCType("BMap::BMFile*"); - mCurrentFct.mFctParams.add(first_decl); + ExpFctsHelper.ExpFctParam firstParam = new ExpFctsHelper.ExpFctParam(); + firstParam.mVarName = ctx.EXPFCTS_IDENTIFIER(0).getText(); + firstParam.mVarDesc = "The pointer to corresponding BMFile."; + firstParam.mIsInput = true; + firstParam.mVarType.fromCType("BMap::BMFile*"); + mCurrentFct.mFctParams.add(firstParam); - ExpFctParamDecl second_decl = new ExpFctParamDecl(); - second_decl.mVarName = ctx.EXPFCTS_IDENTIFIER(1).getText(); - second_decl.mVarDesc = "The CKID of object you accessing."; - second_decl.mIsInput = true; - second_decl.mVarType.fromCType("LibCmo::CK2::CK_ID"); - mCurrentFct.mFctParams.add(second_decl); + ExpFctsHelper.ExpFctParam secondParam = new ExpFctsHelper.ExpFctParam(); + secondParam.mVarName = ctx.EXPFCTS_IDENTIFIER(1).getText(); + secondParam.mVarDesc = "The CKID of object you accessing."; + secondParam.mIsInput = true; + secondParam.mVarType.fromCType("LibCmo::CK2::CK_ID"); + mCurrentFct.mFctParams.add(secondParam); } @Override public void enterFctArgParamIn(ExpFctsParser.FctArgParamInContext ctx) { - mCurrentParam = new ExpFctParamDecl(); + mCurrentParam = new ExpFctsHelper.ExpFctParam(); } @Override @@ -98,7 +94,7 @@ public class ExpFctsWalker extends ExpFctsParserBaseListener { @Override public void enterFctArgParamOut(ExpFctsParser.FctArgParamOutContext ctx) { - mCurrentParam = new ExpFctParamDecl(); + mCurrentParam = new ExpFctsHelper.ExpFctParam(); } @Override diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/IndentHelper.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/IndentHelper.java deleted file mode 100644 index b4b4e63..0000000 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/IndentHelper.java +++ /dev/null @@ -1,42 +0,0 @@ -import java.io.OutputStreamWriter; - -public class IndentHelper { - public IndentHelper(OutputStreamWriter writer) { - mIndent = 0; - mWriter = writer; - } - - private int mIndent; - private OutputStreamWriter mWriter; - - public void inc() { - ++mIndent; - } - - public void dec() { - --mIndent; - } - - private void indent() throws Exception { - for (int i = 0; i < mIndent; ++i) { - mWriter.write(" "); - } - } - - private void lineBreak() throws Exception { - mWriter.write(System.lineSeparator()); - } - - public void puts(String data) throws Exception { - indent(); - mWriter.write(data); - lineBreak(); - } - - public void printf(String fmt, Object... args) throws Exception { - indent(); - mWriter.write(String.format(fmt, args)); - lineBreak(); - } - -} diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/JsonWriter.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/JsonWriter.java index 13c6a99..d5a87b7 100644 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/JsonWriter.java +++ b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/JsonWriter.java @@ -1,5 +1,7 @@ +import java.io.FileOutputStream; import java.io.OutputStreamWriter; -import java.util.Vector; +import java.nio.charset.StandardCharsets; + import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.google.gson.Gson; @@ -7,7 +9,7 @@ import com.google.gson.GsonBuilder; public class JsonWriter { - private static JsonObject writeVariableType(VariableType vt) { + private static JsonObject writeVariableType(ExpFctsHelper.VariableType vt) { JsonObject data = new JsonObject(); JsonArray hierarchy = new JsonArray(); @@ -20,41 +22,44 @@ public class JsonWriter { return data; } - private static JsonObject writeExpFctParamDecl(ExpFctParamDecl paramdecl) { + private static JsonObject writeExpFctParam(ExpFctsHelper.ExpFctParam param) { JsonObject data = new JsonObject(); - data.addProperty("name", paramdecl.mVarName); - data.addProperty("is_input", paramdecl.mIsInput); - data.addProperty("desc", paramdecl.mVarDesc); - data.add("type", writeVariableType(paramdecl.mVarType)); + data.addProperty("name", param.mVarName); + data.addProperty("is_input", param.mIsInput); + data.addProperty("desc", param.mVarDesc); + data.add("type", writeVariableType(param.mVarType)); return data; } - private static JsonObject writeExpFctDecl(ExpFctDecl fctdecl) { + private static JsonObject writeExpFct(ExpFctsHelper.ExpFct fct) { JsonObject data = new JsonObject(); - data.addProperty("name", fctdecl.mFctName); - data.add("return", writeVariableType(fctdecl.mFctRetType)); + data.addProperty("name", fct.mFctName); + data.add("return", writeVariableType(fct.mFctRetType)); - JsonArray paramlist = new JsonArray(); - for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) { - paramlist.add(writeExpFctParamDecl(paramdecl)); + JsonArray paramList = new JsonArray(); + for (ExpFctsHelper.ExpFctParam param : fct.mFctParams) { + paramList.add(writeExpFctParam(param)); } - data.add("params", paramlist); + data.add("params", paramList); return data; } - - public static void writeJson(Vector data) throws Exception { - OutputStreamWriter writer = CommonHelper.openWriter("dest/BMExports.json"); - //Gson gson_instance = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); - Gson gson_instance = new GsonBuilder().disableHtmlEscaping().create(); - - JsonArray fcts = new JsonArray(); - for (ExpFctDecl fctdecl : data) { - fcts.add(writeExpFctDecl(fctdecl)); + + private static JsonArray writeExpFctCollection(ExpFctsHelper.ExpFctCollection fctCollection) { + JsonArray data = new JsonArray(); + for (ExpFctsHelper.ExpFct fct : fctCollection.mFcts) { + data.add(writeExpFct(fct)); } - - writer.write(gson_instance.toJson(fcts)); + return data; + } + + public static void writeJson(ExpFctsHelper.ExpFctCollection data) throws Exception { + FileOutputStream fs = new FileOutputStream(CommonHelper.getOutputFilePath("BMExports.json")); + OutputStreamWriter writer = new OutputStreamWriter(fs, StandardCharsets.UTF_8); + //Gson gsonInstance = new GsonBuilder().serializeNulls().setPrettyPrinting().disableHtmlEscaping().create(); + Gson gsonInstance = new GsonBuilder().serializeNulls().disableHtmlEscaping().create(); + writer.write(gsonInstance.toJson(writeExpFctCollection(data))); writer.close(); } } diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/MainRunner.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/MainRunner.java index e27dfc9..e170034 100644 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/MainRunner.java +++ b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/MainRunner.java @@ -9,9 +9,9 @@ public class MainRunner { public static void main(String[] args) throws Exception { // get interface structure - FileInputStream fs = new FileInputStream("dest/BMExports.hpp"); - CharStream antlrfs = CharStreams.fromStream(fs, StandardCharsets.UTF_8); - ExpFctsLexer lexer = new ExpFctsLexer(antlrfs); + FileInputStream fs = new FileInputStream(CommonHelper.getInputFilePath("BMExports.hpp")); + CharStream antlrStream = CharStreams.fromStream(fs, StandardCharsets.UTF_8); + ExpFctsLexer lexer = new ExpFctsLexer(antlrStream); CommonTokenStream tokens = new CommonTokenStream(lexer); ExpFctsParser parser = new ExpFctsParser(tokens); @@ -23,12 +23,10 @@ public class MainRunner { fs.close(); // get data and write them - Vector result = worker.getResult(); - PythonWriter.writePythonCode(result); - CSharpWriter.writeCSharpCode(result); + ExpFctsHelper.ExpFctCollection result = worker.getResult(); JsonWriter.writeJson(result); // print message. - System.out.println("DONE!"); + System.out.println("Done"); } } diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/PythonWriter.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/PythonWriter.java deleted file mode 100644 index fd297b7..0000000 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/PythonWriter.java +++ /dev/null @@ -1,96 +0,0 @@ -import java.io.OutputStreamWriter; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Vector; -import java.util.stream.Collectors; - -public class PythonWriter { - - private static final Map g_CppTypeMap = cppTypeMapCreator(); - - private static Map cppTypeMapCreator() { - Map cache = new HashMap(); - cache.put("CKSTRING", "CKSTRING"); - cache.put("CKDWORD", "CKDWORD"); - cache.put("CKWORD", "CKWORD"); - cache.put("CKINT", "CKINT"); - cache.put("bool", "bool"); - cache.put("CKFLOAT", "CKFLOAT"); - cache.put("CKBYTE", "CKBYTE"); - cache.put("CK_ID", "CKID"); - cache.put("NakedOutputCallback", "callback"); - cache.put("BMFile", "void"); - cache.put("BMMeshTransition", "void"); - cache.put("VxVector3", "VxVector3"); - cache.put("VxVector2", "VxVector2"); - cache.put("VxColor", "VxColor"); - cache.put("VxMatrix", "VxMatrix"); - cache.put("CK_TEXTURE_SAVEOPTIONS", "enum"); - cache.put("VX_PIXELFORMAT", "enum"); - cache.put("VXLIGHT_TYPE", "enum"); - cache.put("VXTEXTURE_BLENDMODE", "enum"); - cache.put("VXTEXTURE_FILTERMODE", "enum"); - cache.put("VXTEXTURE_ADDRESSMODE", "enum"); - cache.put("VXBLEND_MODE", "enum"); - cache.put("VXFILL_MODE", "enum"); - cache.put("VXSHADE_MODE", "enum"); - cache.put("VXCMPFUNC", "enum"); - cache.put("VXMESH_LITMODE", "enum"); - return Collections.unmodifiableMap(cache); - } - - private static String pythonTypeGetter(ExpFctParamDecl paramdecl) throws IllegalArgumentException { - VariableType vt = paramdecl.mVarType; - if (!paramdecl.mIsInput) { - vt = vt.getPointerOfThis(); - } - - // create string builder for build final type string - StringBuilder sb = new StringBuilder(); - // add type prefix - sb.append("bm_"); - // try getting cpp type from base type - String cpp_type = g_CppTypeMap.get(vt.getBaseType()); - if (cpp_type == null) { - throw new IllegalArgumentException("Unexpected type: " + vt.toCType()); - } - // assign cpp type - sb.append(cpp_type); - // add pointer suffix - if (vt.isPointer()) { - sb.append("_"); - sb.append(String.join("", Collections.nCopies(vt.getPointerLevel(), "p"))); - } - // return built type string. - return sb.toString(); - } - - public static void writePythonCode(Vector data) throws Exception { - OutputStreamWriter writer = CommonHelper.openWriter("dest/BMExports.py"); - IndentHelper helper = new IndentHelper(writer); - - // write function decls - for (ExpFctDecl fctdecl : data) { - // write annotation - // function name - helper.printf("## %s", fctdecl.mFctName); - // param - for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) { - helper.printf("# @param %s[%s] Type: %s. %s%s", paramdecl.mVarName, - CommonHelper.getDoxygenInOutStr(paramdecl.mIsInput), paramdecl.mVarType.toCType(), - (paramdecl.mIsInput ? "" : "Use ctypes.byref(data) pass it. "), paramdecl.mVarDesc); - } - // return val - helper.puts("# @return True if no error, otherwise False."); - - // write real declaration - // first, we need join all param - helper.printf("%s = _create_bmap_func('%s', [%s])", fctdecl.mFctName, fctdecl.mFctName, fctdecl.mFctParams - .stream().map(value -> pythonTypeGetter(value)).collect(Collectors.joining(", "))); - } - - writer.close(); - } - -} diff --git a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/VariableType.java b/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/VariableType.java deleted file mode 100644 index c14f031..0000000 --- a/Assets/CodeGen/BMapBinder/ExpFctsAnalyzer/VariableType.java +++ /dev/null @@ -1,153 +0,0 @@ -import java.util.Collections; -import java.util.Vector; -import java.util.stream.Collectors; - -/** - * The class represent the type of each parameters and function return value. - */ -public class VariableType { - /** - * The base type of this variable removing all ending stars (remove all pointer - * levels) Each item in this a part of namespace and the last one must be the - * type itself (without any namespace restriction). If no namespace restriction - * for this type, this Vector will only have one item. - *

- * For end user, it is enough that knowing the last item is type itself. - */ - private Vector mBaseType; - /** - * The pointer level of this type. It is equal to the count of trailing star of - * this field in C style representation. - */ - private int mPointerLevel; - - /** - * Construct an empty varible type. This is commonly used constructor. - */ - public VariableType() { - mBaseType = new Vector(); - mPointerLevel = 0; - } - - /** - * The constructor used for cloning self. This constructor is only can be used - * by self. - * - * @param base_type The hierarchy of the variable type. - * @param pointer_level The pointer level of new created variable type. - */ - private VariableType(Vector base_type, int pointer_level) { - mBaseType = (Vector) base_type.clone(); - mPointerLevel = pointer_level; - } - - /** - * Set this variable type with a type string in C/C++ style. For example - * "NSTest::NSTest2::MyType**". - * - * @param ctype The type string in C/C++ style. - */ - public void fromCType(String ctype) { - if (ctype.isEmpty()) - throw new IllegalArgumentException("empty string can not be parsed."); - - // get pointer part and name part - int len = ctype.length(); - int star_pos = ctype.indexOf('*'); - String namepart; - if (star_pos == -1) { - // no star - namepart = ctype; - mPointerLevel = 0; - } else { - // has star - if (star_pos == 0) - throw new IllegalArgumentException("base type not found."); - namepart = ctype.substring(0, star_pos); - mPointerLevel = len - star_pos; - } - - // resolve name part - mBaseType.clear(); - for (String item : namepart.split("::")) { - mBaseType.add(item); - } - } - - /** - * Build a type string represented by this variable type in C/C++ style. - * - * @return The type string in C/C++ style. - */ - public String toCType() { - return mBaseType.stream().collect(Collectors.joining("::")) - + String.join("", Collections.nCopies(mPointerLevel, "*")); - } - - /** - * Get the base type of this variable type without any namespace. It just simply - * get the last entry in type hierarchy. - * - * @return The base type string without namespace prefix. - */ - public String getBaseType() { - return mBaseType.lastElement(); - } - - /** - * Check whether this variable type is a pointer. This function just check - * whether the pointer level of this variavle type is zero. - * - * @return True if it is pointer, otherwise false. - */ - public boolean isPointer() { - return mPointerLevel != 0; - } - - /** - * Return the pointer level of this variable type. You can simply assume the - * pointer level is equal to the count of trailing star. - * - * @return The pointer level integer. Zero means that this type is not a - * pointer. - */ - public int getPointerLevel() { - return mPointerLevel; - } - - /** - * Return the clone of the type hierarchy of this variable type. - *

- * It is rarely used. This only should be used when you need the namespace - * hierarchy of this variable type. - * - * @return The clone of current variable type hierarchy. - */ - public Vector getBaseTypeHierarchy() { - return (Vector) mBaseType.clone(); - } - - /** - * Check whether this type is a valid one. It actually check whether type - * hierarchy include at least one entry. - * - * @return True if no problem of this type, otherwise false. - */ - public boolean isValid() { - return mBaseType.size() != 0; - } - - /** - * Return a new created variable type which is the pointer of this variable - * type. - *

- * In internal implementation, it just create a clone of current variable type - * with the increase of pointer level by 1. - * - * @return The new created pointer type of this variable type. - */ - public VariableType getPointerOfThis() { - return new VariableType(mBaseType, mPointerLevel + 1); - } - -} diff --git a/Assets/CodeGen/EnumsMigration/EnumsAnalyzer/JsonWriter.java b/Assets/CodeGen/EnumsMigration/EnumsAnalyzer/JsonWriter.java index 0b2083a..761ab8b 100644 --- a/Assets/CodeGen/EnumsMigration/EnumsAnalyzer/JsonWriter.java +++ b/Assets/CodeGen/EnumsMigration/EnumsAnalyzer/JsonWriter.java @@ -53,7 +53,7 @@ public class JsonWriter { private static void writeJson(String filename, EnumsHelper.BEnumCollection enumCollection) throws Exception { OutputStreamWriter writer = CommonHelper.openOutputFile(filename); - //Gson gsonInstance = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); + //Gson gsonInstance = new GsonBuilder().serializeNulls().setPrettyPrinting().disableHtmlEscaping().create(); Gson gsonInstance = new GsonBuilder().serializeNulls().disableHtmlEscaping().create(); writer.write(gsonInstance.toJson(writeBEnumCollection(enumCollection))); writer.close(); diff --git a/COMPILE.md b/COMPILE.md index a3cf1d4..a8a2215 100644 --- a/COMPILE.md +++ b/COMPILE.md @@ -41,8 +41,6 @@ Following these steps to prepare stb: ### zlib -If you are in Windows, you should download zlib source code and build it with given Visual Studio solution files. The final file we needed is `zlibwapi.dll` with `ZlibDllRelease` build type. - If you are running on non-Windows system. You usually do not need to do anything. Because zlib development environment may be configured by your package manager correctly. If you are in Windows, or in Linux but want to use specific zlib version due to various reasons, following these steps to prepare zlib: @@ -89,7 +87,7 @@ If you are coming from my another project [BallanceBlenderPlugin](https://github It may be useful for the developer who firstly use this project in their own projects. Please note that generated documentation is different in different platforms. * `YYCCommonplace_ROOT`: Set to the install path of YYCCommonplace. -* `stb_ROOT`: Set to the root directory of stb. +* `STB_ROOT`: Set to the root directory of stb. * `ZLIB_ROOT`: Set to the install path of zlib. If you are using zlib which is not build by your own, you usually do not need specify this variable.