ASGlobalFunctionBinder.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  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<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.asDeclaration_.empty())
  114. {
  115. if (declParams.length() > 0)
  116. declParams += ", ";
  117. declParams += conv.asDeclaration_;
  118. }
  119. if (conv.NeedWrapper())
  120. needWrapper = true;
  121. convertedParams.push_back(conv);
  122. }
  123. ConvertedVariable retConv;
  124. try
  125. {
  126. retConv = CppVariableToAS(functionAnalyzer.GetReturnType(), VariableUsage::FunctionReturn);
  127. }
  128. catch (const Exception& e)
  129. {
  130. processedGlobalFunction.registration_ = "// " + string(e.what());
  131. Result::globalFunctions_.push_back(processedGlobalFunction);
  132. return;
  133. }
  134. if (retConv.NeedWrapper())
  135. needWrapper = true;
  136. if (needWrapper)
  137. processedGlobalFunction.glue_ = GenerateWrapper(functionAnalyzer, convertedParams, retConv);
  138. string asReturnType = retConv.asDeclaration_;
  139. string asFunctionName = functionAnalyzer.GetName();
  140. string decl = asReturnType + " " + asFunctionName + "(" + declParams + ")";
  141. processedGlobalFunction.registration_ = "engine->RegisterGlobalFunction(\"" + decl + "\", ";
  142. if (needWrapper)
  143. processedGlobalFunction.registration_ += "asFUNCTION(" + GenerateWrapperName(functionAnalyzer) + "), asCALL_CDECL);";
  144. else
  145. processedGlobalFunction.registration_ += Generate_asFUNCTIONPR(functionAnalyzer) + ", asCALL_CDECL);";
  146. Result::globalFunctions_.push_back(processedGlobalFunction);
  147. // Also register alias if needed
  148. string aliasMark = GetAliasMark(functionAnalyzer);
  149. if (!aliasMark.empty())
  150. {
  151. asFunctionName = CutStart(aliasMark, "BIND_AS_ALIAS_");
  152. decl = asReturnType + " " + asFunctionName + "(" + declParams + ")";
  153. processedGlobalFunction.registration_ = "engine->RegisterGlobalFunction(\"" + decl + "\", ";
  154. if (needWrapper)
  155. processedGlobalFunction.registration_ += "asFUNCTION(" + GenerateWrapperName(functionAnalyzer) + "), asCALL_CDECL);";
  156. else
  157. processedGlobalFunction.registration_ += Generate_asFUNCTIONPR(functionAnalyzer) + ", asCALL_CDECL);";
  158. Result::globalFunctions_.push_back(processedGlobalFunction);
  159. }
  160. }
  161. static void ProcessGlobalFunction(const GlobalFunctionAnalyzer& globalFunctionAnalyzer)
  162. {
  163. if (globalFunctionAnalyzer.IsDefine())
  164. return;
  165. vector<map<string, string>> specializations;
  166. if (globalFunctionAnalyzer.IsTemplate())
  167. {
  168. specializations = GetSpecializations(globalFunctionAnalyzer);
  169. if (!specializations.size())
  170. return;
  171. }
  172. if (Contains(globalFunctionAnalyzer.GetName(), "operator"))
  173. return;
  174. string header = globalFunctionAnalyzer.GetHeaderFile();
  175. Result::AddHeader(header);
  176. if (IsIgnoredHeader(header))
  177. return;
  178. if (Contains(globalFunctionAnalyzer.GetComment(), "NO_BIND"))
  179. {
  180. ProcessedGlobalFunction processedGlobalFunction;
  181. processedGlobalFunction.name_ = globalFunctionAnalyzer.GetName();
  182. processedGlobalFunction.insideDefine_ = InsideDefine(header);
  183. processedGlobalFunction.comment_ = globalFunctionAnalyzer.GetLocation();
  184. processedGlobalFunction.registration_ = "// Not registered because have @nobind mark";
  185. Result::globalFunctions_.push_back(processedGlobalFunction);
  186. return;
  187. }
  188. if (globalFunctionAnalyzer.IsTemplate())
  189. {
  190. for (const TemplateSpecialization& specialization : specializations)
  191. {
  192. GlobalFunctionAnalyzer specializedAnalyzer(globalFunctionAnalyzer.GetMemberdef(), specialization);
  193. BindGlobalFunction(specializedAnalyzer);
  194. }
  195. }
  196. else
  197. {
  198. BindGlobalFunction(globalFunctionAnalyzer);
  199. }
  200. }
  201. void ProcessAllGlobalFunctions()
  202. {
  203. NamespaceAnalyzer namespaceAnalyzer(SourceData::namespaceUrho3D_);
  204. vector<GlobalFunctionAnalyzer> globalFunctionAnalyzers = namespaceAnalyzer.GetFunctions();
  205. for (const GlobalFunctionAnalyzer& globalFunctionAnalyzer : globalFunctionAnalyzers)
  206. ProcessGlobalFunction(globalFunctionAnalyzer);
  207. }
  208. }