JSBHeaderVisitor.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. //
  2. // Copyright (c) 2014-2016 THUNDERBEAST GAMES LLC
  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. #pragma once
  23. #include <Atomic/IO/Log.h>
  24. #include <Atomic/Core/ProcessUtils.h>
  25. using namespace Atomic;
  26. #include "JSBHeader.h"
  27. #include "JSBModule.h"
  28. #include "JSBClass.h"
  29. #include "JSBPackage.h"
  30. #include "JSBFunction.h"
  31. #include "JSBNameVisitor.h"
  32. namespace ToolCore
  33. {
  34. class JSBHeader;
  35. class JSBPrimitiveType;
  36. class JSBHeaderVisitor : public SymbolVisitor
  37. {
  38. JSBHeader* header_;
  39. JSBModule* module_;
  40. TranslationUnit* unit_;
  41. Namespace* globalNamespace_;
  42. public:
  43. JSBHeaderVisitor(JSBHeader* header, TranslationUnit *unit, Namespace* globalNamespace) :
  44. header_(header),
  45. unit_(unit),
  46. globalNamespace_(globalNamespace)
  47. {
  48. module_ = header_->GetModule();
  49. accept(globalNamespace_);
  50. }
  51. String getNameString(const Name* name)
  52. {
  53. JSBNameVisitor nvisitor;
  54. return nvisitor(name);
  55. }
  56. JSBType* processTypeConversion(Type* type)
  57. {
  58. JSBType* jtype = NULL;
  59. if (type->isIntegerType())
  60. {
  61. IntegerType* itype = type->asIntegerType();
  62. jtype = new JSBPrimitiveType(itype->kind());
  63. }
  64. else if (type->isFloatType())
  65. {
  66. jtype = new JSBPrimitiveType(JSBPrimitiveType::Float);
  67. }
  68. else if (type->isNamedType())
  69. {
  70. NamedType* ntype = type->asNamedType();
  71. String classname = getNameString(ntype->name());
  72. if (classname.StartsWith("Atomic::"))
  73. classname.Replace("Atomic::", "");
  74. if (classname == "Vector")
  75. {
  76. if (ntype->name()->asTemplateNameId())
  77. {
  78. const TemplateNameId* tnid = ntype->name()->asTemplateNameId();
  79. FullySpecifiedType pfst = tnid->templateArgumentAt(0);
  80. JSBType* vtype = processTypeConversion(pfst.type());
  81. if (vtype)
  82. {
  83. jtype = new JSBVectorType(vtype);
  84. }
  85. }
  86. }
  87. else if (classname == "String")
  88. {
  89. jtype = new JSBStringType();
  90. }
  91. else if (classname == "StringHash")
  92. {
  93. jtype = new JSBStringHashType();
  94. }
  95. else if (classname == "JS_HEAP_PTR")
  96. {
  97. jtype = new JSBHeapPtrType();
  98. }
  99. else
  100. {
  101. JSBClass* jclass = JSBPackage::GetClassAllPackages(classname);
  102. if (jclass)
  103. jtype = new JSBClassType(jclass);
  104. else
  105. {
  106. // this might be an enum
  107. JSBEnum* jenum = JSBPackage::GetEnumAllPackages(classname);
  108. if (jenum)
  109. jtype = new JSBEnumType(jenum);
  110. }
  111. }
  112. }
  113. else if (type->asUndefinedType())
  114. {
  115. UndefinedType* utype = type->asUndefinedType();
  116. //ErrorExit("Undefined type");
  117. }
  118. return jtype;
  119. }
  120. JSBFunctionType* processFunctionType(FullySpecifiedType fst, bool retType = false)
  121. {
  122. JSBType* jtype = NULL;
  123. Type* type = fst.type();
  124. bool isPointer = false;
  125. bool isSharedPtr = false;
  126. bool isReference = false;
  127. bool isTemplate = false;
  128. bool isConst = false;
  129. if (type->isPointerType())
  130. {
  131. isPointer=true;
  132. FullySpecifiedType pfst = type->asPointerType()->elementType();
  133. type = pfst.type();
  134. }
  135. if (type->isReferenceType())
  136. {
  137. isReference=true;
  138. FullySpecifiedType pfst = type->asReferenceType()->elementType();
  139. type = pfst.type();
  140. isConst = pfst.isConst();
  141. }
  142. if (!isPointer && retType)
  143. {
  144. if (type->isNamedType())
  145. {
  146. NamedType* ntype = type->asNamedType();
  147. if (ntype->name()->asTemplateNameId())
  148. {
  149. const TemplateNameId* tnid = ntype->name()->asTemplateNameId();
  150. String classname = getNameString(tnid->identifier()->asNameId());
  151. if (classname == "SharedPtr")
  152. {
  153. FullySpecifiedType pfst = tnid->templateArgumentAt(0);
  154. type = pfst.type();
  155. isTemplate = true;
  156. isSharedPtr = true;
  157. }
  158. }
  159. }
  160. }
  161. if (fst.isUnsigned())
  162. {
  163. if (type->isUndefinedType())
  164. {
  165. // this happens when just using "unsigned" in code
  166. jtype = new JSBPrimitiveType(JSBPrimitiveType::Int, true);
  167. }
  168. }
  169. if (!jtype)
  170. {
  171. jtype = processTypeConversion(type);
  172. // explicit script string -> StringHash required
  173. if (jtype && jtype->asStringHashType())
  174. isReference = false;
  175. if (fst.isUnsigned() && jtype->asPrimitiveType())
  176. jtype->asPrimitiveType()->isUnsigned_ = true;
  177. }
  178. if (!jtype)
  179. return NULL;
  180. // read only vectors atm
  181. if (!isConst && jtype->asVectorType())
  182. return NULL;
  183. bool skip = false;
  184. // no pointers to prim atm
  185. if (isPointer || isReference)
  186. {
  187. if (jtype->asPrimitiveType())
  188. skip = true;
  189. else if (!retType && !isConst && (jtype->asStringType() || jtype->asStringHashType()))
  190. {
  191. skip = true;
  192. }
  193. if (skip)
  194. return NULL;
  195. }
  196. JSBFunctionType* ftype = new JSBFunctionType(jtype);
  197. ftype->isPointer_ = isPointer;
  198. ftype->isSharedPtr_ = isSharedPtr;
  199. ftype->isReference_ = isReference;
  200. ftype->isTemplate_ = isTemplate;
  201. ftype->isConst_ = isConst;
  202. return ftype;
  203. }
  204. JSBFunctionType* processFunctionArgType(Argument* arg)
  205. {
  206. JSBFunctionType* jtype = processFunctionType(arg->type());
  207. if (!jtype)
  208. return NULL;
  209. jtype->name_ = getNameString(arg->name());
  210. return jtype;
  211. }
  212. JSBFunctionType* processFunctionReturnType(Function* function)
  213. {
  214. if (!function->hasReturnType())
  215. {
  216. return NULL;
  217. }
  218. JSBFunctionType* jtype = processFunctionType(function->returnType(), true);
  219. if (!jtype)
  220. return NULL;
  221. return jtype;
  222. }
  223. JSBFunction* processFunction(JSBClass* klass, Function* function)
  224. {
  225. JSBFunction* jfunction = new JSBFunction(klass);
  226. // don't ... atm
  227. if (function->isVariadic())
  228. return NULL;
  229. String name = getNameString(function->name());
  230. jfunction->SetName(name);
  231. // don't support operators atm
  232. if (name.StartsWith("operator "))
  233. return NULL;
  234. if (name == klass->GetNativeName())
  235. jfunction->SetConstructor();
  236. if (name.StartsWith("~"))
  237. jfunction->SetDestructor();
  238. if (function->isVirtual())
  239. jfunction->SetVirtual(true);
  240. if (function->isStatic())
  241. jfunction->SetStatic(true);
  242. // see if we support return type
  243. if (function->hasReturnType() && !function->returnType().type()->isVoidType())
  244. {
  245. JSBFunctionType* returnType = processFunctionReturnType(function);
  246. if (!returnType)
  247. return NULL;
  248. jfunction->SetReturnType(returnType);
  249. }
  250. if (function->hasArguments())
  251. {
  252. for (unsigned i = 0; i < function->argumentCount(); i++)
  253. {
  254. Symbol* symbol = function->argumentAt(i);
  255. if (symbol->isArgument())
  256. {
  257. Argument* arg = symbol->asArgument();
  258. JSBFunctionType* ftype = processFunctionArgType(arg);
  259. if (!ftype)
  260. {
  261. // if we don't have an initializer, the function cannot be bound
  262. // as unscriptable type
  263. if (!arg->hasInitializer())
  264. return NULL;
  265. // otherwise, break and the optional args will be ignored
  266. break;
  267. }
  268. if (arg->hasInitializer())
  269. {
  270. ftype->initializer_ = arg->initializer()->chars();
  271. if (arg->initializer()->_quotedString)
  272. ftype->initializer_ = "\"" + ftype->initializer_ + "\"";
  273. }
  274. jfunction->AddParameter(ftype);
  275. }
  276. else
  277. {
  278. return NULL;
  279. }
  280. }
  281. }
  282. jfunction->sourceLocation_ = function->sourceLocation();
  283. jfunction->fileName_ = function->fileName();
  284. jfunction->sourceLine_ = function->line();
  285. jfunction->sourceColumn_ = function->column();
  286. //const Token &token = unit_->tokenAt(function->sourceLocation());
  287. //const char* source = unit_->firstSourceChar() + token.byteOffset;
  288. const char* comment = NULL;
  289. for (unsigned i = 0; i < unit_->commentCount(); i++)
  290. {
  291. const Token &tcomment = unit_->commentAt(i);
  292. unsigned line;
  293. unit_->getPosition(tcomment.utf16charsEnd(), &line);
  294. if (line == function->line() - 1)
  295. {
  296. comment = unit_->firstSourceChar() + tcomment.byteOffset;
  297. break;
  298. }
  299. }
  300. if (comment && strlen(comment) > 3)
  301. {
  302. if (comment[0] == '/' && comment[1] == '/' && comment[2] == '/')
  303. {
  304. int index = 3;
  305. while(comment[index] && comment[index] != '\n' && comment[index] != '\r')
  306. {
  307. String docString = jfunction->GetDocString();
  308. docString += comment[index++];
  309. jfunction->SetDocString(docString);
  310. }
  311. }
  312. if (comment[0] == '/' && comment[1] == '*' && comment[2] == '*')
  313. {
  314. int index = 3;
  315. bool foundStar = false;
  316. String docString = jfunction->GetDocString();
  317. while(comment[index])
  318. {
  319. // did we find a star in the last loop?
  320. if (foundStar)
  321. {
  322. // We have a an end of block indicator, let's break
  323. if (comment[index] == '/' && foundStar)
  324. break;
  325. // This is just a star in the comment, not an end of comment indicator. Let's keep it
  326. docString += '*';
  327. }
  328. foundStar = comment[index] == '*';
  329. if (!foundStar)
  330. docString += comment[index];
  331. index++;
  332. }
  333. jfunction->SetDocString(docString);
  334. }
  335. }
  336. return jfunction;
  337. }
  338. virtual bool visit(Namespace *nspace)
  339. {
  340. String name = getNameString(nspace->name());
  341. // LOGINFOF("Namespace: %s", name.CString());
  342. return true;
  343. }
  344. // reject template types
  345. virtual bool visit(Template *t)
  346. {
  347. return false;
  348. }
  349. // enums visited in preprocessor visitor
  350. virtual bool visit(Enum *penum)
  351. {
  352. return false;
  353. }
  354. // global var decl or function
  355. virtual bool visit(Declaration* decl)
  356. {
  357. if (decl->isTypedef())
  358. return true;
  359. FullySpecifiedType dtype = decl->type();
  360. Type* type = dtype.type();
  361. if (type->isPointerType() || type->isReferenceType())
  362. return true;
  363. if (type->asEnumType())
  364. return true;
  365. bool _unsigned = false;
  366. if (dtype.isUnsigned())
  367. _unsigned = true;
  368. if (!type->asFloatType() && !type->asIntegerType() && !_unsigned)
  369. {
  370. return true;
  371. }
  372. String value;
  373. const StringLiteral* init = decl->getInitializer();
  374. if (init)
  375. {
  376. if (init->chars())
  377. value = init->chars();
  378. }
  379. if (type->isIntegerType() || _unsigned)
  380. {
  381. module_->RegisterConstant(getNameString(decl->name()).CString(), value, JSBPrimitiveType::Int, _unsigned);
  382. }
  383. else
  384. {
  385. module_->RegisterConstant(getNameString(decl->name()).CString(), value, JSBPrimitiveType::Float);
  386. }
  387. return true;
  388. }
  389. virtual bool visit(Class *klass)
  390. {
  391. String name = getNameString(klass->name());
  392. JSBClass* jclass = module_->GetClass(name);
  393. if (!jclass)
  394. {
  395. return false;
  396. }
  397. jclass->SetHeader(header_);
  398. for (unsigned i = 0; i < klass->baseClassCount(); i++)
  399. {
  400. BaseClass* baseclass = klass->baseClassAt(i);
  401. String baseclassname = getNameString(baseclass->name());
  402. JSBClass* base = JSBPackage::GetClassAllPackages(baseclassname);
  403. if (!base)
  404. {
  405. LOGINFOF("Warning: %s baseclass %s not in bindings", name.CString(), baseclassname.CString());
  406. }
  407. else
  408. {
  409. jclass->SetBaseClass(base);
  410. }
  411. }
  412. for (unsigned i = 0; i < klass->memberCount(); i++)
  413. {
  414. Symbol* symbol = klass->memberAt(i);
  415. Declaration* decl = symbol->asDeclaration();
  416. // if the function describes the body in the header
  417. Function* function = symbol->asFunction();
  418. // otherwise it could be a decl
  419. if (!function && decl)
  420. function = decl->type()->asFunctionType();
  421. if (function)
  422. {
  423. if (function->isPureVirtual())
  424. jclass->SetAbstract();
  425. // only want public functions
  426. if (!symbol->isPublic())
  427. continue;
  428. JSBFunction* jfunction = processFunction(jclass, function);
  429. if (jfunction)
  430. jclass->AddFunction(jfunction);
  431. }
  432. }
  433. // return false so we don't traverse the class members
  434. return false;
  435. }
  436. };
  437. }