ASGlobalFunctionBinder.cpp 8.4 KB

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