ASUtils.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858
  1. // Copyright (c) 2008-2022 the Urho3D project
  2. // License: MIT
  3. #include "ASUtils.h"
  4. #include "Tuning.h"
  5. #include "Utils.h"
  6. #include "XmlAnalyzer.h"
  7. #include "XmlSourceData.h"
  8. #include <cassert>
  9. #include <regex>
  10. using namespace std;
  11. using namespace pugi;
  12. namespace ASBindingGenerator
  13. {
  14. // https://www.angelcode.com/angelscript/sdk/docs/manual/doc_datatypes_primitives.html
  15. // https://en.cppreference.com/w/cpp/language/types
  16. string CppPrimitiveTypeToAS(const string& cppType)
  17. {
  18. if (cppType == "bool")
  19. return "bool";
  20. if (cppType == "char" || cppType == "signed char" || cppType == "i8")
  21. return "int8";
  22. if (cppType == "unsigned char" || cppType == "u8")
  23. return "uint8";
  24. if (cppType == "short" || cppType == "i16")
  25. return "int16";
  26. if (cppType == "unsigned short" || cppType == "u16")
  27. return "uint16";
  28. if (cppType == "int" || cppType == "i32")
  29. return "int";
  30. if (cppType == "unsigned" || cppType == "unsigned int" || cppType == "u32")
  31. return "uint";
  32. if (cppType == "long long" || cppType == "i64")
  33. return "int64";
  34. if (cppType == "unsigned long long" || cppType == "u64")
  35. return "uint64";
  36. if (cppType == "float")
  37. return "float";
  38. if (cppType == "double")
  39. return "double";
  40. // Types below are registered in Manual.cpp
  41. if (cppType == "long")
  42. return "long";
  43. if (cppType == "unsigned long")
  44. return "ulong";
  45. if (cppType == "size_t")
  46. return "size_t";
  47. if (cppType == "SDL_JoystickID")
  48. return "SDL_JoystickID";
  49. throw Exception(cppType + " not a primitive type");
  50. }
  51. string JoinASDeclarations(const vector<ConvertedVariable>& vars)
  52. {
  53. string result;
  54. for (const ConvertedVariable& var : vars)
  55. {
  56. if (!var.asDeclaration_.empty())
  57. {
  58. if (!result.empty())
  59. result += ", ";
  60. result += var.asDeclaration_;
  61. }
  62. }
  63. return result;
  64. }
  65. string JoinCppDeclarations(const string& firstCppDeclaration, const vector<ConvertedVariable>& vars)
  66. {
  67. string result = firstCppDeclaration;
  68. for (const ConvertedVariable& var : vars)
  69. {
  70. if (!var.cppDeclaration_.empty())
  71. {
  72. if (!result.empty())
  73. result += ", ";
  74. result += var.cppDeclaration_;
  75. }
  76. }
  77. return result;
  78. }
  79. string JoinCppDeclarations(const vector<ConvertedVariable>& vars)
  80. {
  81. return JoinCppDeclarations("", vars);
  82. }
  83. shared_ptr<EnumAnalyzer> FindEnum(const string& name)
  84. {
  85. NamespaceAnalyzer namespaceAnalyzer(SourceData::namespaceUrho3D_);
  86. vector<EnumAnalyzer> enumAnalyzers = namespaceAnalyzer.GetEnums();
  87. for (const EnumAnalyzer& enumAnalyzer : enumAnalyzers)
  88. {
  89. if (enumAnalyzer.GetTypeName() == name)
  90. return make_shared<EnumAnalyzer>(enumAnalyzer);
  91. }
  92. return shared_ptr<EnumAnalyzer>();
  93. }
  94. static bool IsUsing(const string& identifier)
  95. {
  96. for (xml_node memberdef : SourceData::usings_)
  97. {
  98. UsingAnalyzer usingAnalyzer(memberdef);
  99. if (usingAnalyzer.GetName() == identifier)
  100. return true;
  101. }
  102. return false;
  103. }
  104. bool IsKnownCppType(const string& name)
  105. {
  106. static vector<string> _knownTypes = {
  107. "void",
  108. "bool",
  109. "size_t",
  110. "char",
  111. "signed char",
  112. "i8",
  113. "unsigned char",
  114. "u8",
  115. "short",
  116. "i16",
  117. "unsigned short",
  118. "u16",
  119. "int",
  120. "i32",
  121. "long", // Size is compiler-dependent
  122. "unsigned",
  123. "unsigned int",
  124. "u32",
  125. "unsigned long", // Size is compiler-dependent
  126. "long long",
  127. "i64",
  128. "unsigned long long",
  129. "u64",
  130. "float",
  131. "double",
  132. "SDL_JoystickID",
  133. // TODO: Remove
  134. "VariantMap",
  135. };
  136. if (CONTAINS(_knownTypes, name))
  137. return true;
  138. if (SourceData::classesByName_.find(name) != SourceData::classesByName_.end())
  139. return true;
  140. if (SourceData::enums_.find(name) != SourceData::enums_.end())
  141. return true;
  142. if (EndsWith(name, "Flags"))
  143. return true;
  144. return false;
  145. }
  146. shared_ptr<ClassAnalyzer> FindClassByName(const string& name)
  147. {
  148. auto it = SourceData::classesByName_.find(name);
  149. if (it != SourceData::classesByName_.end())
  150. {
  151. xml_node compounddef = it->second;
  152. return make_shared<ClassAnalyzer>(compounddef);
  153. }
  154. // using VariantVector = Vector<Variant>
  155. return shared_ptr<ClassAnalyzer>();
  156. }
  157. shared_ptr<ClassAnalyzer> FindClassByID(const string& id)
  158. {
  159. auto it = SourceData::classesByID_.find(id);
  160. if (it != SourceData::classesByID_.end())
  161. {
  162. xml_node compounddef = it->second;
  163. return make_shared<ClassAnalyzer>(compounddef);
  164. }
  165. // using VariantVector = Vector<Variant>
  166. return shared_ptr<ClassAnalyzer>();
  167. }
  168. // Variable name can be empty for function return type
  169. ConvertedVariable CppVariableToAS(const TypeAnalyzer& type, VariableUsage usage, const string& name, const string& defaultValue)
  170. {
  171. ConvertedVariable result;
  172. if (usage == VariableUsage::PostfixIncDecParameter)
  173. {
  174. result.glue_ = " " + type.ToString() + " " + name + "{};\n";
  175. return result;
  176. }
  177. if (type.IsRvalueReference() || type.IsDoublePointer() || type.IsRefToPointer())
  178. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  179. string cppTypeName = type.GetNameWithTemplateParams();
  180. if (cppTypeName == "void")
  181. {
  182. if (usage == VariableUsage::FunctionReturn && !type.IsPointer())
  183. {
  184. result.asDeclaration_ = "void";
  185. result.cppDeclaration_ = "void";
  186. return result;
  187. }
  188. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  189. }
  190. if (cppTypeName == "Context")
  191. {
  192. if (usage == VariableUsage::FunctionParameter && type.IsPointer())
  193. {
  194. result.glue_ = " " + type.ToString() + " " + name + " = GetScriptContext();\n";
  195. return result;
  196. }
  197. throw Exception("Error: type \"" + type.ToString() + "\" can used only as function parameter");
  198. }
  199. // Works with both Vector<String> and Vector<String>&
  200. if (cppTypeName == "Vector<String>" || cppTypeName == "StringVector")
  201. {
  202. // Works with both Vector<String> and Vector<String>&
  203. if (usage == VariableUsage::FunctionReturn && !type.IsPointer())
  204. {
  205. result.asDeclaration_ = "Array<String>@";
  206. result.cppDeclaration_ = "CScriptArray*";
  207. result.glue_ = "return VectorToArray<String>(result, \"Array<String>\");\n";
  208. return result;
  209. }
  210. if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
  211. {
  212. string newCppVarName = name + "_conv";
  213. //result->asDecl_ = "String[]&";
  214. result.asDeclaration_ = "Array<String>@+";
  215. result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
  216. result.glue_ = " " + cppTypeName + " " + name + " = ArrayToVector<String>(" + newCppVarName + ");\n";
  217. if (!defaultValue.empty())
  218. {
  219. assert(defaultValue == "Vector< String >()");
  220. //result->asDecl_ += " = Array<String>()";
  221. result.asDeclaration_ += " = null";
  222. }
  223. return result;
  224. }
  225. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  226. }
  227. smatch match;
  228. regex_match(cppTypeName, match, regex("SharedPtr<(\\w+)>"));
  229. if (!match.empty())
  230. {
  231. string cppSubtypeName = match[1].str();
  232. string asSubtypeName;
  233. try
  234. {
  235. asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
  236. }
  237. catch (...)
  238. {
  239. asSubtypeName = cppSubtypeName;
  240. }
  241. if (cppSubtypeName == "WorkItem") // TODO autodetect
  242. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  243. if (usage == VariableUsage::FunctionReturn)
  244. {
  245. result.asDeclaration_ = asSubtypeName + "@+";
  246. result.cppDeclaration_ = cppSubtypeName + "*";
  247. result.glue_ = "return result.Detach();\n";
  248. return result;
  249. }
  250. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  251. }
  252. regex_match(cppTypeName, match, regex("Vector<SharedPtr<(\\w+)>>"));
  253. if (!match.empty())
  254. {
  255. string cppSubtypeName = match[1].str();
  256. string asSubtypeName;
  257. try
  258. {
  259. asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
  260. }
  261. catch (...)
  262. {
  263. asSubtypeName = cppSubtypeName;
  264. }
  265. if (cppSubtypeName == "WorkItem") // TODO autodetect
  266. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  267. if (usage == VariableUsage::FunctionReturn)
  268. {
  269. result.asDeclaration_ = "Array<" + asSubtypeName + "@>@";
  270. result.cppDeclaration_ = "CScriptArray*";
  271. // Which variant is correct/better?
  272. #if 0
  273. result->glueResult_ = "return VectorToArray<SharedPtr<" + cppTypeName + ">>(result, \"Array<" + asTypeName + "@>@\");\n";
  274. #else
  275. result.glue_ = "return VectorToHandleArray(result, \"Array<" + asSubtypeName + "@>\");\n";
  276. #endif
  277. return result;
  278. }
  279. if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
  280. {
  281. string newCppVarName = name + "_conv";
  282. result.asDeclaration_ = "Array<" + asSubtypeName + "@>@+";
  283. result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
  284. result.glue_ = " " + cppTypeName + " " + name + " = HandleArrayToVector<" + cppSubtypeName + ">(" + newCppVarName + ");\n";
  285. assert(defaultValue.empty()); // TODO: make
  286. return result;
  287. }
  288. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  289. }
  290. regex_match(cppTypeName, match, regex("PODVector<(\\w+)\\*>"));
  291. if (!match.empty())
  292. {
  293. string cppSubtypeName = match[1].str();
  294. string asSubtypeName;
  295. try
  296. {
  297. asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
  298. }
  299. catch (...)
  300. {
  301. asSubtypeName = cppSubtypeName;
  302. }
  303. if (usage == VariableUsage::FunctionReturn)
  304. {
  305. result.asDeclaration_ = "Array<" + asSubtypeName + "@>@";
  306. result.cppDeclaration_ = "CScriptArray*";
  307. result.glue_ = "return VectorToHandleArray(result, \"Array<" + asSubtypeName + "@>\");\n";
  308. return result;
  309. }
  310. if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
  311. {
  312. string newCppVarName = name + "_conv";
  313. result.asDeclaration_ = "Array<" + asSubtypeName + "@>@";
  314. result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
  315. result.glue_ = " " + cppTypeName + " " + name + " = ArrayToVector<" + cppSubtypeName + "*>(" + newCppVarName + ");\n";
  316. assert(defaultValue.empty()); // TODO: make
  317. return result;
  318. }
  319. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  320. }
  321. regex_match(cppTypeName, match, regex("PODVector<(\\w+)>"));
  322. if (!match.empty())
  323. {
  324. string cppSubtypeName = match[1].str();
  325. string asSubtypeName;
  326. try
  327. {
  328. asSubtypeName = CppPrimitiveTypeToAS(cppSubtypeName);
  329. }
  330. catch (...)
  331. {
  332. asSubtypeName = cppSubtypeName;
  333. }
  334. if (usage == VariableUsage::FunctionReturn && type.IsConst() == type.IsReference())
  335. {
  336. result.asDeclaration_ = "Array<" + asSubtypeName + ">@";
  337. result.cppDeclaration_ = "CScriptArray*";
  338. result.glue_ = "return VectorToArray(result, \"Array<" + asSubtypeName + ">\");\n";
  339. return result;
  340. }
  341. if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
  342. {
  343. string newCppVarName = name + "_conv";
  344. result.asDeclaration_ = "Array<" + asSubtypeName + ">@+";
  345. result.cppDeclaration_ = "CScriptArray* " + newCppVarName;
  346. result.glue_ = " " + cppTypeName + " " + name + " = ArrayToVector<" + cppSubtypeName + ">(" + newCppVarName + ");\n";
  347. assert(defaultValue.empty()); // TODO: make
  348. return result;
  349. }
  350. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  351. }
  352. if (!IsKnownCppType(cppTypeName))
  353. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  354. shared_ptr<ClassAnalyzer> analyzer = FindClassByName(cppTypeName);
  355. if (analyzer && analyzer->IsInternal())
  356. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
  357. if (analyzer && Contains(analyzer->GetComment(), "NO_BIND"))
  358. throw Exception("Error: type \"" + cppTypeName + "\" can not automatically bind bacause have @nobind mark");
  359. if (analyzer && analyzer->IsAbstract() && !(analyzer->IsRefCounted() || analyzer->IsNoCount()))
  360. throw Exception("Error: type \"" + cppTypeName + "\" can not bind bacause abstract value");
  361. // analyzer can be null for simple types (int, float) or if type "using VariantVector = Vector<Variant>"
  362. // TODO add to type info "IsUsing"
  363. // TODO add description to TypeAnalyzer::GetClass()
  364. if (IsUsing(cppTypeName) && cppTypeName != "VariantMap")
  365. throw Exception("Using \"" + cppTypeName + "\" can not automatically bind");
  366. string asTypeName;
  367. try
  368. {
  369. asTypeName = CppPrimitiveTypeToAS(cppTypeName);
  370. }
  371. catch (...)
  372. {
  373. asTypeName = cppTypeName;
  374. }
  375. if (Contains(asTypeName, '<'))
  376. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  377. if (Contains(type.ToString(), "::"))
  378. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
  379. if (usage == VariableUsage::FunctionParameter && type.IsConst() && type.IsReference())
  380. {
  381. result.asDeclaration_ = "const " + asTypeName + "&in";
  382. result.cppDeclaration_ = type.ToString();
  383. if (!name.empty())
  384. result.cppDeclaration_ += " " + name;
  385. if (!defaultValue.empty())
  386. {
  387. string asDefaultValue = CppValueToAS(defaultValue);
  388. asDefaultValue = ReplaceAll(asDefaultValue, "\"", "\\\"");
  389. result.asDeclaration_ += " = " + asDefaultValue;
  390. }
  391. return result;
  392. }
  393. result.asDeclaration_ = asTypeName;
  394. if (type.IsReference())
  395. {
  396. result.asDeclaration_ += "&";
  397. }
  398. else if (type.IsPointer())
  399. {
  400. shared_ptr<ClassAnalyzer> analyzer = FindClassByName(cppTypeName);
  401. if (analyzer && (analyzer->IsRefCounted() || analyzer->IsNoCount()))
  402. result.asDeclaration_ = result.asDeclaration_ + "@" + (analyzer->IsNoCount() ? "" : "+");
  403. else
  404. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  405. }
  406. result.cppDeclaration_ = type.ToString();
  407. if (!name.empty())
  408. result.cppDeclaration_ += " " + name;
  409. if (usage == VariableUsage::FunctionReturn && type.IsConst() && !type.IsPointer())
  410. result.asDeclaration_ = "const " + result.asDeclaration_;
  411. if (!defaultValue.empty())
  412. {
  413. string asDefaultValue = CppValueToAS(defaultValue);
  414. asDefaultValue = ReplaceAll(asDefaultValue, "\"", "\\\"");
  415. result.asDeclaration_ += " = " + asDefaultValue;
  416. }
  417. return result;
  418. }
  419. string HideUnnamedType(const string& name)
  420. {
  421. regex rgx("@\\d+");
  422. return regex_replace(name, rgx, "@?");
  423. }
  424. string CppTypeToAS(const TypeAnalyzer& type, TypeUsage typeUsage)
  425. {
  426. if (Contains(type.GetName(), "@")) // Unnamed union inside class
  427. throw Exception("Error: type \"" + HideUnnamedType(type.ToString()) + "\" can not automatically bind");
  428. if (type.IsRvalueReference() || type.IsDoublePointer() || type.IsRefToPointer())
  429. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  430. string cppTypeName = type.GetNameWithTemplateParams();
  431. if (cppTypeName == "Context" && typeUsage == TypeUsage::FunctionReturn)
  432. throw Exception("Error: type \"" + type.ToString() + "\" can not be returned");
  433. if (!IsKnownCppType(type.GetNameWithTemplateParams()))
  434. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  435. shared_ptr<ClassAnalyzer> analyzer = FindClassByName(type.GetNameWithTemplateParams());
  436. if (analyzer && analyzer->IsInternal())
  437. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
  438. if (analyzer && Contains(analyzer->GetComment(), "NO_BIND"))
  439. throw Exception("Error: type \"" + cppTypeName + "\" can not automatically bind bacause have @nobind mark");
  440. // analyzer can be null for simple types (int, float) or if type "using VariantVector = Vector<Variant>"
  441. // TODO add to type info "IsUsing"
  442. // TODO add description to TypeAnalyzer::GetClass()
  443. if (IsUsing(cppTypeName) && cppTypeName != "VariantMap")
  444. throw Exception("Using \"" + cppTypeName + "\" can not automatically bind");
  445. string asTypeName;
  446. try
  447. {
  448. asTypeName = CppPrimitiveTypeToAS(cppTypeName);
  449. }
  450. catch (...)
  451. {
  452. asTypeName = cppTypeName;
  453. }
  454. if (asTypeName == "void" && type.IsPointer())
  455. throw Exception("Error: type \"void*\" can not automatically bind");
  456. if (Contains(asTypeName, '<'))
  457. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  458. if (Contains(type.ToString(), "::"))
  459. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind bacause internal");
  460. if (type.IsConst() && type.IsReference() && typeUsage == TypeUsage::FunctionParameter)
  461. return "const " + asTypeName + "&in";
  462. string result = asTypeName;
  463. if (type.IsReference())
  464. {
  465. result += "&";
  466. }
  467. else if (type.IsPointer())
  468. {
  469. shared_ptr<ClassAnalyzer> analyzer = FindClassByName(type.GetNameWithTemplateParams());
  470. if (analyzer && (analyzer->IsRefCounted() || analyzer->IsNoCount()))
  471. result = result + "@" + (analyzer->IsNoCount() ? "" : "+");
  472. else
  473. throw Exception("Error: type \"" + type.ToString() + "\" can not automatically bind");
  474. }
  475. if (typeUsage == TypeUsage::FunctionReturn && type.IsConst() && !type.IsPointer())
  476. result = "const " + result;
  477. return result;
  478. }
  479. string CppValueToAS(const string& cppValue)
  480. {
  481. if (cppValue == "nullptr")
  482. return "null";
  483. if (cppValue == "Variant::emptyVariantMap")
  484. return "VariantMap()";
  485. if (cppValue == "NPOS")
  486. return "String::NPOS";
  487. return cppValue;
  488. }
  489. // =================================================================================
  490. static string GenerateFunctionWrapperName(xml_node memberdef)
  491. {
  492. TypeAnalyzer returnType = ExtractType(memberdef);
  493. string result = ExtractType(memberdef).ToString() + "_" + ExtractName(memberdef);
  494. vector<ParamAnalyzer> params = ExtractParams(memberdef);
  495. if (params.size() == 0)
  496. {
  497. result += "_void";
  498. }
  499. else
  500. {
  501. for (ParamAnalyzer param : params)
  502. {
  503. result += "_" + param.GetType().ToString();
  504. }
  505. }
  506. result = ReplaceAll(result, "=", "eq");
  507. result = ReplaceAll(result, "<", "les");
  508. result = ReplaceAll(result, ">", "gre");
  509. result = ReplaceAll(result, "*", "star");
  510. result = ReplaceAll(result, "/", "div");
  511. result = ReplaceAll(result, "+", "plus");
  512. result = ReplaceAll(result, "-", "min");
  513. result = ReplaceAll(result, "[", "lbr");
  514. result = ReplaceAll(result, "]", "rbr");
  515. result = ReplaceAll(result, ":", "col");
  516. result = ReplaceAll(result, " ", "sp");
  517. result = ReplaceAll(result, "&", "amp");
  518. return result;
  519. }
  520. string GenerateWrapperName(const GlobalFunctionAnalyzer& functionAnalyzer)
  521. {
  522. return GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef());
  523. }
  524. string GenerateWrapperName(const ClassStaticFunctionAnalyzer& functionAnalyzer)
  525. {
  526. return functionAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(functionAnalyzer.GetMemberdef());
  527. }
  528. string GenerateWrapperName(const MethodAnalyzer& methodAnalyzer, bool templateVersion)
  529. {
  530. if (templateVersion)
  531. return methodAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(methodAnalyzer.GetMemberdef()) + "_template";
  532. else
  533. return methodAnalyzer.GetClassName() + "_" + GenerateFunctionWrapperName(methodAnalyzer.GetMemberdef());
  534. }
  535. // =================================================================================
  536. string GenerateWrapper(const GlobalFunctionAnalyzer& functionAnalyzer, const vector<ConvertedVariable>& convertedParams, const ConvertedVariable& convertedReturn)
  537. {
  538. string result;
  539. string glueReturnType = convertedReturn.cppDeclaration_;
  540. result =
  541. "static " + glueReturnType + " " + GenerateWrapperName(functionAnalyzer) + "(" + JoinCppDeclarations(convertedParams) + ")\n"
  542. "{\n";
  543. for (size_t i = 0; i < convertedParams.size(); i++)
  544. result += convertedParams[i].glue_;
  545. if (glueReturnType != "void")
  546. result += " " + functionAnalyzer.GetReturnType().ToString() + " result = ";
  547. else
  548. result += " ";
  549. result += functionAnalyzer.GetName() + "(" + functionAnalyzer.JoinParamsNames() + ");\n";
  550. if (!convertedReturn.glue_.empty())
  551. result += " " + convertedReturn.glue_;
  552. else if (glueReturnType != "void")
  553. result += " return result;\n";
  554. result += "}";
  555. return result;
  556. }
  557. string GenerateWrapper(const ClassStaticFunctionAnalyzer& functionAnalyzer, bool templateVersion, const vector<ConvertedVariable>& convertedParams, const ConvertedVariable& convertedReturn)
  558. {
  559. string result = templateVersion ? "template <class T> " : "static ";
  560. string className = templateVersion ? "T" : functionAnalyzer.GetClassName();
  561. string glueReturnType = convertedReturn.cppDeclaration_;
  562. result +=
  563. glueReturnType + " " + GenerateWrapperName(functionAnalyzer) + "(" + JoinCppDeclarations(convertedParams) + ")\n"
  564. "{\n";
  565. for (size_t i = 0; i < convertedParams.size(); i++)
  566. result += convertedParams[i].glue_;
  567. if (glueReturnType != "void")
  568. result += " " + functionAnalyzer.GetReturnType().ToString() + " result = ";
  569. else
  570. result += " ";
  571. result += className + "::" + functionAnalyzer.GetName() + "(" + functionAnalyzer.JoinParamsNames() + ");\n";
  572. if (!convertedReturn.glue_.empty())
  573. result += " " + convertedReturn.glue_;
  574. else if (glueReturnType != "void")
  575. result += " return result;\n";
  576. result += "}\n";
  577. return result;
  578. }
  579. string GenerateWrapper(const MethodAnalyzer& methodAnalyzer, bool templateVersion, const vector<ConvertedVariable>& convertedParams, const ConvertedVariable& convertedReturn)
  580. {
  581. string result = templateVersion ? "template <class T> " : "static ";
  582. string className = templateVersion ? "T" : methodAnalyzer.GetClassName();
  583. string glueReturnType = convertedReturn.cppDeclaration_;
  584. result +=
  585. glueReturnType + " " + GenerateWrapperName(methodAnalyzer, templateVersion) + "(" + JoinCppDeclarations(className + "* _ptr", convertedParams) + ")\n"
  586. "{\n";
  587. for (size_t i = 0; i < convertedParams.size(); i++)
  588. result += convertedParams[i].glue_;
  589. if (glueReturnType != "void")
  590. result += " " + methodAnalyzer.GetReturnType().ToString() + " result = ";
  591. else
  592. result += " ";
  593. result += "_ptr->" + methodAnalyzer.GetName() + "(" + methodAnalyzer.JoinParamsNames() + ");\n";
  594. if (!convertedReturn.glue_.empty())
  595. result += " " + convertedReturn.glue_;
  596. else if (glueReturnType != "void")
  597. result += " return result;\n";
  598. result += "}\n";
  599. return result;
  600. }
  601. string GenerateConstructorWrapper(const MethodAnalyzer& methodAnalyzer, const vector<ConvertedVariable>& convertedParams)
  602. {
  603. string className = methodAnalyzer.GetClassName();
  604. string result =
  605. "static void " + GenerateWrapperName(methodAnalyzer) + "(" + JoinCppDeclarations(className + "* _ptr", convertedParams) + ")\n"
  606. "{\n";
  607. for (size_t i = 0; i < convertedParams.size(); i++)
  608. result += convertedParams[i].glue_;
  609. result +=
  610. " new(_ptr) " + className + "(" + methodAnalyzer.JoinParamsNames() + ");\n"
  611. "}\n";
  612. return result;
  613. }
  614. string GenerateFactoryWrapper(const MethodAnalyzer& methodAnalyzer, const vector<ConvertedVariable>& convertedParams)
  615. {
  616. string className = methodAnalyzer.GetClassName();
  617. string result =
  618. "static " + className + "* " + GenerateWrapperName(methodAnalyzer) + "(" + JoinCppDeclarations(convertedParams) + ")\n"
  619. "{\n";
  620. for (size_t i = 0; i < convertedParams.size(); i++)
  621. result += convertedParams[i].glue_;
  622. result +=
  623. " return new " + className + "(" + methodAnalyzer.JoinParamsNames() + ");\n"
  624. "}\n";
  625. return result;
  626. }
  627. // =================================================================================
  628. string Generate_asFUNCTIONPR(const GlobalFunctionAnalyzer& functionAnalyzer)
  629. {
  630. string functionName = functionAnalyzer.GetName();
  631. string cppParams = "(" + JoinParamsTypes(functionAnalyzer.GetMemberdef(), functionAnalyzer.GetSpecialization()) + ")";
  632. string returnType = functionAnalyzer.GetReturnType().ToString();
  633. return "AS_FUNCTIONPR(" + functionName + ", " + cppParams + ", " + returnType + ")";
  634. }
  635. string Generate_asFUNCTIONPR(const ClassStaticFunctionAnalyzer& functionAnalyzer, bool templateVersion)
  636. {
  637. string className = functionAnalyzer.GetClassName();
  638. string functionName = functionAnalyzer.GetName();
  639. string cppParams = "(" + JoinParamsTypes(functionAnalyzer.GetMemberdef(), functionAnalyzer.GetSpecialization()) + ")";
  640. string returnType = functionAnalyzer.GetReturnType().ToString();
  641. if (templateVersion)
  642. return "AS_FUNCTIONPR(T::" + functionName + ", " + cppParams + ", " + returnType + ")";
  643. else
  644. return "AS_FUNCTIONPR(" + className + "::" + functionName + ", " + cppParams + ", " + returnType + ")";
  645. }
  646. string Generate_asMETHODPR(const MethodAnalyzer& methodAnalyzer, bool templateVersion)
  647. {
  648. string className = methodAnalyzer.GetClassName();
  649. string functionName = methodAnalyzer.GetName();
  650. string cppParams = "(" + JoinParamsTypes(methodAnalyzer.GetMemberdef(), methodAnalyzer.GetSpecialization()) + ")";
  651. if (methodAnalyzer.IsConst())
  652. cppParams += " const";
  653. string returnType = methodAnalyzer.GetReturnType().ToString();
  654. if (templateVersion)
  655. return "AS_METHODPR(T, " + functionName + ", " + cppParams + ", " + returnType + ")";
  656. else
  657. return "AS_METHODPR(" + className + ", " + functionName + ", " + cppParams + ", " + returnType + ")";
  658. }
  659. } // namespace ASBindingGenerator