ASGlobalFunctionBinder.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #include "ASResult.h"
  4. #include "ASUtils.h"
  5. #include "Tuning.h"
  6. #include "Utils.h"
  7. #include "XmlAnalyzer.h"
  8. #include "XmlSourceData.h"
  9. #include <cassert>
  10. #include <map>
  11. #include <regex>
  12. using namespace std;
  13. namespace ASBindingGenerator
  14. {
  15. static string GetAliasMark(const GlobalFunctionAnalyzer& functionAnalyzer)
  16. {
  17. string comment = functionAnalyzer.GetComment();
  18. smatch match;
  19. regex_match(comment, match, regex(".*\\b(BIND_AS_ALIAS_.+?)\\b.*"));
  20. if (match.size() == 2)
  21. return match[1].str();
  22. return "";
  23. }
  24. static vector<map<string, string>> GetSpecializations(const GlobalFunctionAnalyzer& functionAnalyzer)
  25. {
  26. vector<string> templateParams = functionAnalyzer.GetTemplateParams();
  27. vector<map<string, string>> result;
  28. string comment = functionAnalyzer.GetComment();
  29. smatch match;
  30. if (templateParams.size() == 1)
  31. {
  32. regex rgx("\\bSPECIALIZATION_([^_]+?)\\b");
  33. string::const_iterator searchStart(comment.cbegin());
  34. while (regex_search(searchStart, comment.cend(), match, rgx))
  35. {
  36. map<string, string> specialization;
  37. specialization[templateParams[0]] = match[1].str();
  38. searchStart = match.suffix().first;
  39. result.push_back(specialization);
  40. }
  41. }
  42. else if (templateParams.size() == 2)
  43. {
  44. regex rgx("\\bSPECIALIZATION_([^_]+?)_([^_]+?)\\b");
  45. string::const_iterator searchStart(comment.cbegin());
  46. while (regex_search(searchStart, comment.cend(), match, rgx))
  47. {
  48. map<string, string> specialization;
  49. specialization[templateParams[0]] = match[1].str();
  50. specialization[templateParams[1]] = match[2].str();
  51. searchStart = match.suffix().first;
  52. result.push_back(specialization);
  53. }
  54. }
  55. else if (templateParams.size() == 3)
  56. {
  57. regex rgx("\\bSPECIALIZATION_([^_]+?)_([^_]+?)_([^_]+?)\\b");
  58. string::const_iterator searchStart(comment.cbegin());
  59. while (regex_search(searchStart, comment.cend(), match, rgx))
  60. {
  61. map<string, string> specialization;
  62. specialization[templateParams[0]] = match[1].str();
  63. specialization[templateParams[1]] = match[2].str();
  64. specialization[templateParams[2]] = match[3].str();
  65. searchStart = match.suffix().first;
  66. result.push_back(specialization);
  67. }
  68. }
  69. return result;
  70. }
  71. static void BindGlobalFunction(const GlobalFunctionAnalyzer& functionAnalyzer)
  72. {
  73. vector<ParamAnalyzer> params = functionAnalyzer.GetParams();
  74. string outGlue;
  75. bool needWrapper = false;
  76. vector<ConvertedVariable> convertedParams;
  77. ProcessedGlobalFunction processedGlobalFunction;
  78. processedGlobalFunction.name_ = functionAnalyzer.GetName();
  79. processedGlobalFunction.comment_ = functionAnalyzer.GetLocation();
  80. processedGlobalFunction.insideDefine_ = InsideDefine(functionAnalyzer.GetHeaderFile());
  81. for (const ParamAnalyzer& param : params)
  82. {
  83. ConvertedVariable conv;
  84. try
  85. {
  86. conv = CppVariableToAS(param.GetType(), VariableUsage::FunctionParameter, param.GetDeclname(), param.GetDefval());
  87. }
  88. catch (const Exception& e)
  89. {
  90. processedGlobalFunction.registration_ = "// " + string(e.what());
  91. Result::globalFunctions_.push_back(processedGlobalFunction);
  92. return;
  93. }
  94. if (conv.NeedWrapper())
  95. needWrapper = true;
  96. convertedParams.push_back(conv);
  97. }
  98. ConvertedVariable retConv;
  99. try
  100. {
  101. retConv = CppVariableToAS(functionAnalyzer.GetReturnType(), VariableUsage::FunctionReturn);
  102. }
  103. catch (const Exception& e)
  104. {
  105. processedGlobalFunction.registration_ = "// " + string(e.what());
  106. Result::globalFunctions_.push_back(processedGlobalFunction);
  107. return;
  108. }
  109. if (retConv.NeedWrapper())
  110. needWrapper = true;
  111. if (needWrapper)
  112. processedGlobalFunction.glue_ = GenerateWrapper(functionAnalyzer, convertedParams, retConv);
  113. string asReturnType = retConv.asDeclaration_;
  114. string asFunctionName = functionAnalyzer.GetName();
  115. string decl = asReturnType + " " + asFunctionName + "(" + JoinASDeclarations(convertedParams) + ")";
  116. processedGlobalFunction.registration_ = "engine->RegisterGlobalFunction(\"" + decl + "\", ";
  117. if (needWrapper)
  118. processedGlobalFunction.registration_ += "AS_FUNCTION(" + GenerateWrapperName(functionAnalyzer) + "), AS_CALL_CDECL);";
  119. else
  120. processedGlobalFunction.registration_ += Generate_asFUNCTIONPR(functionAnalyzer) + ", AS_CALL_CDECL);";
  121. Result::globalFunctions_.push_back(processedGlobalFunction);
  122. // Also register alias if needed
  123. string aliasMark = GetAliasMark(functionAnalyzer);
  124. if (!aliasMark.empty())
  125. {
  126. asFunctionName = CutStart(aliasMark, "BIND_AS_ALIAS_");
  127. decl = asReturnType + " " + asFunctionName + "(" + JoinASDeclarations(convertedParams) + ")";
  128. processedGlobalFunction.registration_ = "engine->RegisterGlobalFunction(\"" + decl + "\", ";
  129. if (needWrapper)
  130. processedGlobalFunction.registration_ += "AS_FUNCTION(" + GenerateWrapperName(functionAnalyzer) + "), AS_CALL_CDECL);";
  131. else
  132. processedGlobalFunction.registration_ += Generate_asFUNCTIONPR(functionAnalyzer) + ", AS_CALL_CDECL);";
  133. Result::globalFunctions_.push_back(processedGlobalFunction);
  134. }
  135. }
  136. static void ProcessGlobalFunction(const GlobalFunctionAnalyzer& globalFunctionAnalyzer)
  137. {
  138. if (globalFunctionAnalyzer.IsDefine())
  139. return;
  140. vector<map<string, string>> specializations;
  141. if (globalFunctionAnalyzer.IsTemplate())
  142. {
  143. specializations = GetSpecializations(globalFunctionAnalyzer);
  144. if (!specializations.size())
  145. return;
  146. }
  147. if (Contains(globalFunctionAnalyzer.GetName(), "operator"))
  148. return;
  149. string header = globalFunctionAnalyzer.GetHeaderFile();
  150. Result::AddHeader(header);
  151. if (IsIgnoredHeader(header))
  152. return;
  153. if (Contains(globalFunctionAnalyzer.GetComment(), "NO_BIND"))
  154. {
  155. ProcessedGlobalFunction processedGlobalFunction;
  156. processedGlobalFunction.name_ = globalFunctionAnalyzer.GetName();
  157. processedGlobalFunction.insideDefine_ = InsideDefine(header);
  158. processedGlobalFunction.comment_ = globalFunctionAnalyzer.GetLocation();
  159. processedGlobalFunction.registration_ = "// Not registered because have @nobind mark";
  160. Result::globalFunctions_.push_back(processedGlobalFunction);
  161. return;
  162. }
  163. if (globalFunctionAnalyzer.IsTemplate())
  164. {
  165. for (const TemplateSpecialization& specialization : specializations)
  166. {
  167. GlobalFunctionAnalyzer specializedAnalyzer(globalFunctionAnalyzer.GetMemberdef(), specialization);
  168. BindGlobalFunction(specializedAnalyzer);
  169. }
  170. }
  171. else
  172. {
  173. BindGlobalFunction(globalFunctionAnalyzer);
  174. }
  175. }
  176. void ProcessAllGlobalFunctions()
  177. {
  178. NamespaceAnalyzer namespaceAnalyzer(SourceData::namespaceUrho3D_);
  179. vector<GlobalFunctionAnalyzer> globalFunctionAnalyzers = namespaceAnalyzer.GetFunctions();
  180. for (const GlobalFunctionAnalyzer& globalFunctionAnalyzer : globalFunctionAnalyzers)
  181. ProcessGlobalFunction(globalFunctionAnalyzer);
  182. }
  183. }