ASUtils.cpp 27 KB

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