JSBHeaderVisitor.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  2. // Please see LICENSE.md in repository root for license information
  3. // https://github.com/AtomicGameEngine/AtomicGameEngine
  4. #pragma once
  5. #include <Atomic/IO/Log.h>
  6. #include <Atomic/Core/ProcessUtils.h>
  7. #include "JSBHeader.h"
  8. #include "JSBModule.h"
  9. #include "JSBindings.h"
  10. #include "JSBClass.h"
  11. #include "JSBFunction.h"
  12. #include "JSBNameVisitor.h"
  13. class JSBHeader;
  14. class JSBHeaderVisitor : public SymbolVisitor
  15. {
  16. JSBHeader* header_;
  17. JSBModule* module_;
  18. JSBindings* bindings_;
  19. TranslationUnit* unit_;
  20. Namespace* globalNamespace_;
  21. public:
  22. JSBHeaderVisitor(JSBHeader* header, TranslationUnit *unit, Namespace* globalNamespace) :
  23. header_(header),
  24. unit_(unit),
  25. globalNamespace_(globalNamespace)
  26. {
  27. module_ = header_->module_;
  28. bindings_ = module_->bindings_;
  29. accept(globalNamespace_);
  30. }
  31. String getNameString(const Name* name)
  32. {
  33. JSBNameVisitor nvisitor;
  34. return nvisitor(name);
  35. }
  36. JSBType* processTypeConversion(Type* type)
  37. {
  38. JSBType* jtype = NULL;
  39. if (type->isIntegerType())
  40. {
  41. IntegerType* itype = type->asIntegerType();
  42. jtype = new JSBPrimitiveType(itype->kind());
  43. }
  44. if (type->isFloatType())
  45. {
  46. jtype = new JSBPrimitiveType(JSBPrimitiveType::Float);
  47. }
  48. else if (type->isNamedType())
  49. {
  50. NamedType* ntype = type->asNamedType();
  51. String classname = getNameString(ntype->name());
  52. if (classname == "String")
  53. {
  54. jtype = new JSBStringType();
  55. }
  56. else if (classname == "StringHash")
  57. {
  58. jtype = new JSBStringHashType();
  59. }
  60. else if (classname == "JS_HEAP_PTR")
  61. {
  62. jtype = new JSBHeapPtrType();
  63. }
  64. else
  65. {
  66. JSBClass* jclass = bindings_->GetClass(classname);
  67. if (jclass)
  68. jtype = new JSBClassType(jclass);
  69. else
  70. {
  71. // this might be an enum
  72. JSBEnum* jenum = bindings_->GetEnum(classname);
  73. if (jenum)
  74. jtype = new JSBEnumType(jenum);
  75. }
  76. }
  77. }
  78. else if (type->asUndefinedType())
  79. {
  80. UndefinedType* utype = type->asUndefinedType();
  81. //ErrorExit("Undefined type");
  82. }
  83. return jtype;
  84. }
  85. JSBFunctionType* processFunctionType(FullySpecifiedType fst, bool retType = false)
  86. {
  87. JSBType* jtype = NULL;
  88. Type* type = fst.type();
  89. bool isPointer = false;
  90. bool isSharedPtr = false;
  91. bool isReference = false;
  92. bool isTemplate = false;
  93. bool isConst = false;
  94. if (type->isPointerType())
  95. {
  96. isPointer=true;
  97. FullySpecifiedType pfst = type->asPointerType()->elementType();
  98. type = pfst.type();
  99. }
  100. if (type->isReferenceType())
  101. {
  102. isReference=true;
  103. FullySpecifiedType pfst = type->asReferenceType()->elementType();
  104. type = pfst.type();
  105. isConst = pfst.isConst();
  106. }
  107. if (!isPointer && retType)
  108. {
  109. if (type->isNamedType())
  110. {
  111. NamedType* ntype = type->asNamedType();
  112. if (ntype->name()->asTemplateNameId())
  113. {
  114. const TemplateNameId* tnid = ntype->name()->asTemplateNameId();
  115. String classname = getNameString(tnid->identifier()->asNameId());
  116. if (classname == "SharedPtr")
  117. {
  118. FullySpecifiedType pfst = tnid->templateArgumentAt(0);
  119. type = pfst.type();
  120. isTemplate = true;
  121. }
  122. }
  123. }
  124. }
  125. if (fst.isUnsigned())
  126. {
  127. if (type->isUndefinedType())
  128. {
  129. // this happens when just using "unsigned" in code
  130. jtype = new JSBPrimitiveType(JSBPrimitiveType::Int, true);
  131. }
  132. }
  133. if (!jtype)
  134. jtype = processTypeConversion(type);
  135. if (!jtype)
  136. return NULL;
  137. bool skip = false;
  138. // no pointers to prim atm
  139. if (isPointer || isReference)
  140. {
  141. if (jtype->asPrimitiveType())
  142. skip = true;
  143. else if (!retType && !isConst && (jtype->asStringType() || jtype->asStringHashType()))
  144. {
  145. skip = true;
  146. }
  147. if (skip)
  148. return NULL;
  149. }
  150. JSBFunctionType* ftype = new JSBFunctionType(jtype);
  151. ftype->isPointer_ = isPointer;
  152. ftype->isSharedPtr_ = isSharedPtr;
  153. ftype->isReference_ = isReference;
  154. ftype->isTemplate_ = isTemplate;
  155. return ftype;
  156. }
  157. JSBFunctionType* processFunctionArgType(Argument* arg)
  158. {
  159. JSBFunctionType* jtype = processFunctionType(arg->type());
  160. if (!jtype)
  161. return NULL;
  162. jtype->name_ = getNameString(arg->name());
  163. return jtype;
  164. }
  165. JSBFunctionType* processFunctionReturnType(Function* function)
  166. {
  167. if (!function->hasReturnType())
  168. {
  169. return NULL;
  170. }
  171. JSBFunctionType* jtype = processFunctionType(function->returnType(), true);
  172. if (!jtype)
  173. return NULL;
  174. return jtype;
  175. }
  176. JSBFunction* processFunction(JSBClass* klass, Function* function)
  177. {
  178. JSBFunction* jfunction = new JSBFunction(klass);
  179. // don't ... atm
  180. if (function->isVariadic())
  181. return NULL;
  182. jfunction->name_ = getNameString(function->name());
  183. // don't support operators atm
  184. if (jfunction->name_.StartsWith("operator "))
  185. return NULL;
  186. if (jfunction->name_ == klass->GetClassName())
  187. jfunction->isConstructor_ = true;
  188. if (jfunction->name_.StartsWith("~"))
  189. jfunction->isDestructor_ = true;
  190. // see if we support return type
  191. if (function->hasReturnType() && !function->returnType().type()->isVoidType())
  192. {
  193. jfunction->returnType_ = processFunctionReturnType(function);
  194. if (!jfunction->returnType_)
  195. return NULL;
  196. }
  197. if (function->hasArguments())
  198. {
  199. for (unsigned i = 0; i < function->argumentCount(); i++)
  200. {
  201. Symbol* symbol = function->argumentAt(i);
  202. if (symbol->isArgument())
  203. {
  204. Argument* arg = symbol->asArgument();
  205. JSBFunctionType* ftype = processFunctionArgType(arg);
  206. if (!ftype)
  207. return NULL;
  208. if (arg->hasInitializer())
  209. {
  210. ftype->initializer_ = arg->initializer()->chars();
  211. if (ftype->initializer_.StartsWith("\\"))
  212. ftype->initializer_ = "\"" + ftype->initializer_ + "\"";
  213. }
  214. jfunction->AddParameter(ftype);
  215. }
  216. else
  217. {
  218. return NULL;
  219. }
  220. }
  221. }
  222. jfunction->sourceLocation_ = function->sourceLocation();
  223. jfunction->fileName_ = function->fileName();
  224. jfunction->sourceLine_ = function->line();
  225. jfunction->sourceColumn_ = function->column();
  226. //const Token &token = unit_->tokenAt(function->sourceLocation());
  227. //const char* source = unit_->firstSourceChar() + token.byteOffset;
  228. const char* comment = NULL;
  229. for (unsigned i = 0; i < unit_->commentCount(); i++)
  230. {
  231. const Token &tcomment = unit_->commentAt(i);
  232. unsigned line;
  233. unit_->getPosition(tcomment.utf16charOffset, &line);
  234. if (line == function->line() - 1)
  235. {
  236. comment = unit_->firstSourceChar() + tcomment.byteOffset;
  237. break;
  238. }
  239. }
  240. if (comment && strlen(comment) > 3)
  241. {
  242. if (comment[0] == '/' && comment[1] == '/' && comment[2] == '/')
  243. {
  244. int index = 3;
  245. while(comment[index] && comment[index] != '\n' && comment[index] != '\r')
  246. jfunction->docString_ += comment[index++];
  247. }
  248. }
  249. return jfunction;
  250. }
  251. virtual bool visit(Namespace *nspace)
  252. {
  253. String name = getNameString(nspace->name());
  254. // LOGINFOF("Namespace: %s", name.CString());
  255. return true;
  256. }
  257. // reject template types
  258. virtual bool visit(Template *t)
  259. {
  260. return false;
  261. }
  262. // enums visited in preprocessor visitor
  263. virtual bool visit(Enum *penum)
  264. {
  265. return false;
  266. }
  267. // global var decl or function
  268. virtual bool visit(Declaration* decl)
  269. {
  270. FullySpecifiedType dtype = decl->type();
  271. Type* type = dtype.type();
  272. if (type->isPointerType() || type->isReferenceType())
  273. return true;
  274. if (type->asEnumType())
  275. return true;
  276. if (!type->asFloatType() && !type->asIntegerType())
  277. return true;
  278. module_->RegisterConstant(getNameString(decl->name()).CString());
  279. return true;
  280. }
  281. virtual bool visit(Class *klass)
  282. {
  283. String name = getNameString(klass->name());
  284. JSBClass* jclass = bindings_->GetClass(name);
  285. if (!jclass)
  286. {
  287. return false;
  288. }
  289. jclass->SetHeader(header_);
  290. //LOGINFOF("Adding Class: %s to Module: %s", name.CString(), module_->name_.CString());
  291. jclass->SetModule(module_);
  292. module_->AddClass(jclass);
  293. for (unsigned i = 0; i < klass->baseClassCount(); i++)
  294. {
  295. BaseClass* baseclass = klass->baseClassAt(i);
  296. String baseclassname = getNameString(baseclass->name());
  297. JSBClass* base = bindings_->GetClass(baseclassname);
  298. if (!base)
  299. {
  300. LOGINFOF("Warning: %s baseclass %s not in bindings", name.CString(), baseclassname.CString());
  301. }
  302. else
  303. {
  304. jclass->AddBaseClass(base);
  305. }
  306. }
  307. for (unsigned i = 0; i < klass->memberCount(); i++)
  308. {
  309. Symbol* symbol = klass->memberAt(i);
  310. Declaration* decl = symbol->asDeclaration();
  311. // if the function describes the body in the header
  312. Function* function = symbol->asFunction();
  313. // otherwise it could be a decl
  314. if (!function && decl)
  315. function = decl->type()->asFunctionType();
  316. if (function)
  317. {
  318. if (function->isPureVirtual())
  319. jclass->setAbstract(true);
  320. // only want public functions
  321. if (!symbol->isPublic())
  322. continue;
  323. JSBFunction* jfunction = processFunction(jclass, function);
  324. if (jfunction)
  325. jclass->AddFunction(jfunction);
  326. }
  327. }
  328. // return false so we don't traverse the class members
  329. return false;
  330. }
  331. };