ASGlobalFunctionBinder.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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 <regex>
  29. #include <cassert>
  30. #include <map>
  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 shared_ptr<ASGeneratedFile_GlobalFunctions> _result;
  90. static void BindGlobalFunction(const GlobalFunctionAnalyzer& functionAnalyzer, const map<string, string>& templateSpecialization = map<string, string>())
  91. {
  92. string declParams = "";
  93. vector<ParamAnalyzer> params = functionAnalyzer.GetParams(templateSpecialization);
  94. string outGlue;
  95. bool needWrapper = false;
  96. vector<shared_ptr<FuncParamConv> > convertedParams;
  97. for (size_t i = 0; i < params.size(); i++)
  98. {
  99. ParamAnalyzer param = params[i];
  100. shared_ptr<FuncParamConv> conv = CppFunctionParamToAS(i, param);
  101. if (!conv->success_)
  102. {
  103. _result->reg_ << " // " << conv->errorMessage_ << "\n";
  104. return;
  105. }
  106. if (declParams.length() > 0)
  107. declParams += ", ";
  108. declParams += conv->asDecl_;
  109. if (conv->NeedWrapper())
  110. needWrapper = true;
  111. convertedParams.push_back(conv);
  112. }
  113. shared_ptr<FuncReturnTypeConv> retConv = CppFunctionReturnTypeToAS(functionAnalyzer.GetReturnType(templateSpecialization));
  114. if (!retConv->success_)
  115. {
  116. _result->reg_ << " // " << GetLastErrorMessage() << "\n";
  117. return;
  118. }
  119. if (retConv->needWrapper_)
  120. needWrapper = true;
  121. if (needWrapper)
  122. _result->glue_ << GenerateWrapper(functionAnalyzer, convertedParams, retConv);
  123. string asReturnType = retConv->asReturnType_;
  124. string asFunctionName = functionAnalyzer.GetName();
  125. string decl = asReturnType + " " + asFunctionName + "(" + declParams + ")";
  126. _result->reg_ << " engine->RegisterGlobalFunction(\"" << decl << "\", ";
  127. if (needWrapper)
  128. _result->reg_ << "asFUNCTION(" << GenerateWrapperName(functionAnalyzer) << "), asCALL_CDECL);\n";
  129. else
  130. _result->reg_ << Generate_asFUNCTIONPR(functionAnalyzer, templateSpecialization) << ", asCALL_CDECL);\n";
  131. // Also register alias if needed
  132. string aliasMark = GetAliasMark(functionAnalyzer);
  133. if (!aliasMark.empty())
  134. {
  135. asFunctionName = CutStart(aliasMark, "BIND_AS_ALIAS_");
  136. decl = asReturnType + " " + asFunctionName + "(" + declParams + ")";
  137. _result->reg_ << " engine->RegisterGlobalFunction(\"" << decl << "\", ";
  138. if (needWrapper)
  139. _result->reg_ << "asFUNCTION(" << GenerateWrapperName(functionAnalyzer) << "), asCALL_CDECL);\n";
  140. else
  141. _result->reg_ << Generate_asFUNCTIONPR(functionAnalyzer, templateSpecialization) << ", asCALL_CDECL);\n";
  142. }
  143. }
  144. static void ProcessGlobalFunction(const GlobalFunctionAnalyzer& functionAnalyzer)
  145. {
  146. if (functionAnalyzer.IsDefine())
  147. return;
  148. vector<map<string, string> > specializations;
  149. if (functionAnalyzer.IsTemplate())
  150. {
  151. specializations = GetSpecializations(functionAnalyzer);
  152. if (!specializations.size())
  153. return;
  154. }
  155. if (Contains(functionAnalyzer.GetName(), "operator"))
  156. return;
  157. string header = functionAnalyzer.GetHeaderFile();
  158. if (IsIgnoredHeader(header))
  159. {
  160. _result->AddIgnoredHeader(header);
  161. return;
  162. }
  163. _result->AddHeader(header);
  164. string insideDefine = InsideDefine(header);
  165. if (!insideDefine.empty())
  166. _result->reg_ << "#ifdef " << insideDefine << "\n";
  167. _result->reg_ << " // " << functionAnalyzer.GetLocation() << "\n";
  168. if (Contains(functionAnalyzer.GetComment(), "NO_BIND"))
  169. {
  170. _result->reg_ << " // Not registered because have @nobind mark\n";
  171. if (!insideDefine.empty())
  172. _result->reg_ << "#endif\n";
  173. return;
  174. }
  175. if (functionAnalyzer.IsTemplate())
  176. {
  177. for (map<string, string> specialization : specializations)
  178. BindGlobalFunction(functionAnalyzer, specialization);
  179. }
  180. else
  181. {
  182. BindGlobalFunction(functionAnalyzer);
  183. }
  184. if (!insideDefine.empty())
  185. _result->reg_ << "#endif\n";
  186. }
  187. void ProcessAllGlobalFunctions(const string& outputBasePath)
  188. {
  189. string outputPath = outputBasePath + "/Source/Urho3D/AngelScript/Generated_GlobalFunctions.cpp";
  190. NamespaceAnalyzer namespaceAnalyzer(SourceData::namespaceUrho3D_);
  191. vector<GlobalFunctionAnalyzer> globalFunctionAnalyzers = namespaceAnalyzer.GetFunctions();
  192. _result = make_shared<ASGeneratedFile_GlobalFunctions>(outputPath, "ASRegisterGenerated_GlobalFunctions");
  193. for (GlobalFunctionAnalyzer globalFunctionAnalyzer : globalFunctionAnalyzers)
  194. ProcessGlobalFunction(globalFunctionAnalyzer);
  195. _result->Save();
  196. }
  197. }