ASGlobalFunctionBinder.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "ASResult.h"
  23. #include "ASUtils.h"
  24. #include "Tuning.h"
  25. #include "Utils.h"
  26. #include "XmlAnalyzer.h"
  27. #include "XmlSourceData.h"
  28. #include <cassert>
  29. #include <map>
  30. #include <regex>
  31. namespace ASBindingGenerator
  32. {
  33. static string GetAliasMark(const GlobalFunctionAnalyzer& functionAnalyzer)
  34. {
  35. string comment = functionAnalyzer.GetComment();
  36. smatch match;
  37. regex_match(comment, match, regex(".*\\b(BIND_AS_ALIAS_.+?)\\b.*"));
  38. if (match.size() == 2)
  39. return match[1].str();
  40. return "";
  41. }
  42. static vector<map<string, string>> GetSpecializations(const GlobalFunctionAnalyzer& functionAnalyzer)
  43. {
  44. vector<string> templateParams = functionAnalyzer.GetTemplateParams();
  45. vector<map<string, string>> result;
  46. string comment = functionAnalyzer.GetComment();
  47. smatch match;
  48. if (templateParams.size() == 1)
  49. {
  50. regex rgx("\\bSPECIALIZATION_([^_]+?)\\b");
  51. string::const_iterator searchStart(comment.cbegin());
  52. while (regex_search(searchStart, comment.cend(), match, rgx))
  53. {
  54. map<string, string> specialization;
  55. specialization[templateParams[0]] = match[1].str();
  56. searchStart = match.suffix().first;
  57. result.push_back(specialization);
  58. }
  59. }
  60. else if (templateParams.size() == 2)
  61. {
  62. regex rgx("\\bSPECIALIZATION_([^_]+?)_([^_]+?)\\b");
  63. string::const_iterator searchStart(comment.cbegin());
  64. while (regex_search(searchStart, comment.cend(), match, rgx))
  65. {
  66. map<string, string> specialization;
  67. specialization[templateParams[0]] = match[1].str();
  68. specialization[templateParams[1]] = match[2].str();
  69. searchStart = match.suffix().first;
  70. result.push_back(specialization);
  71. }
  72. }
  73. else if (templateParams.size() == 3)
  74. {
  75. regex rgx("\\bSPECIALIZATION_([^_]+?)_([^_]+?)_([^_]+?)\\b");
  76. string::const_iterator searchStart(comment.cbegin());
  77. while (regex_search(searchStart, comment.cend(), match, rgx))
  78. {
  79. map<string, string> specialization;
  80. specialization[templateParams[0]] = match[1].str();
  81. specialization[templateParams[1]] = match[2].str();
  82. specialization[templateParams[2]] = match[3].str();
  83. searchStart = match.suffix().first;
  84. result.push_back(specialization);
  85. }
  86. }
  87. return result;
  88. }
  89. static void BindGlobalFunction(const GlobalFunctionAnalyzer& functionAnalyzer)
  90. {
  91. string declParams = "";
  92. vector<ParamAnalyzer> params = functionAnalyzer.GetParams();
  93. string outGlue;
  94. bool needWrapper = false;
  95. vector<shared_ptr<FuncParamConv>> convertedParams;
  96. ProcessedGlobalFunction processedGlobalFunction;
  97. processedGlobalFunction.name_ = functionAnalyzer.GetName();
  98. processedGlobalFunction.comment_ = functionAnalyzer.GetLocation();
  99. processedGlobalFunction.insideDefine_ = InsideDefine(functionAnalyzer.GetHeaderFile());
  100. for (const ParamAnalyzer& param : params)
  101. {
  102. shared_ptr<FuncParamConv> conv = CppFunctionParamToAS(param);
  103. if (!conv->success_)
  104. {
  105. processedGlobalFunction.registration_ = "// " + conv->errorMessage_;
  106. Result::globalFunctions_.push_back(processedGlobalFunction);
  107. return;
  108. }
  109. if (declParams.length() > 0)
  110. declParams += ", ";
  111. declParams += conv->asDecl_;
  112. if (conv->NeedWrapper())
  113. needWrapper = true;
  114. convertedParams.push_back(conv);
  115. }
  116. shared_ptr<FuncReturnTypeConv> retConv = CppFunctionReturnTypeToAS(functionAnalyzer.GetReturnType());
  117. if (!retConv->success_)
  118. {
  119. processedGlobalFunction.registration_ = "// " + GetLastErrorMessage();
  120. Result::globalFunctions_.push_back(processedGlobalFunction);
  121. return;
  122. }
  123. if (retConv->needWrapper_)
  124. needWrapper = true;
  125. if (needWrapper)
  126. processedGlobalFunction.glue_ = GenerateWrapper(functionAnalyzer, convertedParams, retConv);
  127. string asReturnType = retConv->asReturnType_;
  128. string asFunctionName = functionAnalyzer.GetName();
  129. string decl = asReturnType + " " + asFunctionName + "(" + declParams + ")";
  130. processedGlobalFunction.registration_ = "engine->RegisterGlobalFunction(\"" + decl + "\", ";
  131. if (needWrapper)
  132. processedGlobalFunction.registration_ += "asFUNCTION(" + GenerateWrapperName(functionAnalyzer) + "), asCALL_CDECL);";
  133. else
  134. processedGlobalFunction.registration_ += Generate_asFUNCTIONPR(functionAnalyzer) + ", asCALL_CDECL);";
  135. Result::globalFunctions_.push_back(processedGlobalFunction);
  136. // Also register alias if needed
  137. string aliasMark = GetAliasMark(functionAnalyzer);
  138. if (!aliasMark.empty())
  139. {
  140. asFunctionName = CutStart(aliasMark, "BIND_AS_ALIAS_");
  141. decl = asReturnType + " " + asFunctionName + "(" + declParams + ")";
  142. processedGlobalFunction.registration_ = "engine->RegisterGlobalFunction(\"" + decl + "\", ";
  143. if (needWrapper)
  144. processedGlobalFunction.registration_ += "asFUNCTION(" + GenerateWrapperName(functionAnalyzer) + "), asCALL_CDECL);";
  145. else
  146. processedGlobalFunction.registration_ += Generate_asFUNCTIONPR(functionAnalyzer) + ", asCALL_CDECL);";
  147. Result::globalFunctions_.push_back(processedGlobalFunction);
  148. }
  149. }
  150. static void ProcessGlobalFunction(const GlobalFunctionAnalyzer& globalFunctionAnalyzer)
  151. {
  152. if (globalFunctionAnalyzer.IsDefine())
  153. return;
  154. vector<map<string, string>> specializations;
  155. if (globalFunctionAnalyzer.IsTemplate())
  156. {
  157. specializations = GetSpecializations(globalFunctionAnalyzer);
  158. if (!specializations.size())
  159. return;
  160. }
  161. if (Contains(globalFunctionAnalyzer.GetName(), "operator"))
  162. return;
  163. string header = globalFunctionAnalyzer.GetHeaderFile();
  164. Result::AddHeader(header);
  165. if (IsIgnoredHeader(header))
  166. return;
  167. if (Contains(globalFunctionAnalyzer.GetComment(), "NO_BIND"))
  168. {
  169. ProcessedGlobalFunction processedGlobalFunction;
  170. processedGlobalFunction.name_ = globalFunctionAnalyzer.GetName();
  171. processedGlobalFunction.insideDefine_ = InsideDefine(header);
  172. processedGlobalFunction.comment_ = globalFunctionAnalyzer.GetLocation();
  173. processedGlobalFunction.registration_ = "// Not registered because have @nobind mark";
  174. Result::globalFunctions_.push_back(processedGlobalFunction);
  175. return;
  176. }
  177. if (globalFunctionAnalyzer.IsTemplate())
  178. {
  179. for (const TemplateSpecialization& specialization : specializations)
  180. {
  181. GlobalFunctionAnalyzer specializedAnalyzer(globalFunctionAnalyzer.GetMemberdef(), specialization);
  182. BindGlobalFunction(specializedAnalyzer);
  183. }
  184. }
  185. else
  186. {
  187. BindGlobalFunction(globalFunctionAnalyzer);
  188. }
  189. }
  190. void ProcessAllGlobalFunctions()
  191. {
  192. NamespaceAnalyzer namespaceAnalyzer(SourceData::namespaceUrho3D_);
  193. vector<GlobalFunctionAnalyzer> globalFunctionAnalyzers = namespaceAnalyzer.GetFunctions();
  194. for (const GlobalFunctionAnalyzer& globalFunctionAnalyzer : globalFunctionAnalyzers)
  195. ProcessGlobalFunction(globalFunctionAnalyzer);
  196. }
  197. }