functionRemap.cxx 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. // Filename: functionRemap.cxx
  2. // Created by: drose (19Sep01)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved
  8. //
  9. // All use of this software is subject to the terms of the Panda 3d
  10. // Software license. You should have received a copy of this license
  11. // along with this source code; you will also find a current copy of
  12. // the license at http://etc.cmu.edu/panda3d/docs/license/ .
  13. //
  14. // To contact the maintainers of this program write to
  15. // [email protected] .
  16. //
  17. ////////////////////////////////////////////////////////////////////
  18. #include "functionRemap.h"
  19. #include "typeManager.h"
  20. #include "interrogate.h"
  21. #include "parameterRemap.h"
  22. #include "parameterRemapThis.h"
  23. #include "interfaceMaker.h"
  24. #include "interrogateBuilder.h"
  25. #include "interrogateDatabase.h"
  26. #include "cppInstance.h"
  27. #include "cppFunctionType.h"
  28. #include "cppParameterList.h"
  29. #include "cppReferenceType.h"
  30. #include "interrogateType.h"
  31. #include "pnotify.h"
  32. extern bool inside_python_native;
  33. ////////////////////////////////////////////////////////////////////
  34. // Function: FunctionRemap::Constructor
  35. // Access: Public
  36. // Description:
  37. ////////////////////////////////////////////////////////////////////
  38. FunctionRemap::
  39. FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc,
  40. CPPInstance *cppfunc, int num_default_parameters,
  41. InterfaceMaker *interface_maker) {
  42. _return_type = (ParameterRemap *)NULL;
  43. _void_return = true;
  44. _ForcedVoidReturn = false;
  45. _has_this = false;
  46. _blocking = false;
  47. _const_method = false;
  48. _first_true_parameter = 0;
  49. _num_default_parameters = num_default_parameters;
  50. _type = T_normal;
  51. _wrapper_index = 0;
  52. _return_value_needs_management = false;
  53. _return_value_destructor = 0;
  54. _manage_reference_count = false;
  55. _cppfunc = cppfunc;
  56. _ftype = _cppfunc->_type->as_function_type();
  57. _cpptype = itype._cpptype;
  58. _cppscope = itype._cppscope;
  59. _is_valid = setup_properties(ifunc, interface_maker);
  60. }
  61. ////////////////////////////////////////////////////////////////////
  62. // Function: FunctionRemap::Destructor
  63. // Access: Public
  64. // Description:
  65. ////////////////////////////////////////////////////////////////////
  66. FunctionRemap::
  67. ~FunctionRemap() {
  68. }
  69. ////////////////////////////////////////////////////////////////////
  70. // Function: FunctionRemap::get_parameter_name
  71. // Access: Public
  72. // Description: Returns a string that will be a suitable name for the
  73. // nth parameter in the generated code. This may not
  74. // correspond to the name of the parameter in the
  75. // original code.
  76. ////////////////////////////////////////////////////////////////////
  77. string FunctionRemap::
  78. get_parameter_name(int n) const {
  79. ostringstream str;
  80. str << "param" << n;
  81. return str.str();
  82. }
  83. ////////////////////////////////////////////////////////////////////
  84. // Function: FunctionRemap::call_function
  85. // Access: Public
  86. // Description: Writes a sequence of commands to the given output
  87. // stream to call the wrapped function. The parameter
  88. // values are taken from pexprs, if it is nonempty, or
  89. // are assumed to be simply the names of the parameters,
  90. // if it is empty.
  91. //
  92. // The return value is the expression to return, if we
  93. // are returning a value, or the empty string if we
  94. // return nothing.
  95. ////////////////////////////////////////////////////////////////////
  96. string FunctionRemap::call_function(ostream &out, int indent_level, bool convert_result,
  97. const string &container, const vector_string &pexprs) const {
  98. string return_expr;
  99. if (_type == T_destructor) {
  100. // A destructor wrapper is just a wrapper around the delete operator.
  101. assert(!container.empty());
  102. assert(_cpptype != (CPPType *)NULL);
  103. if (TypeManager::is_reference_count(_cpptype)) {
  104. // Except for a reference-count type object, in which case the
  105. // destructor is a wrapper around unref_delete().
  106. InterfaceMaker::indent(out, indent_level)
  107. << "unref_delete(" << container << ");\n";
  108. } else {
  109. if(inside_python_native)
  110. InterfaceMaker::indent(out, indent_level) << "Dtool_Py_Delete(self); \n";
  111. else
  112. InterfaceMaker::indent(out, indent_level) << " delete " << container << ";\n";
  113. }
  114. } else if (_type == T_typecast_method) {
  115. // A typecast method can be invoked implicitly.
  116. string cast_expr =
  117. "(" + _return_type->get_orig_type()->get_local_name(&parser) +
  118. ")(*" + container + ")";
  119. if (!convert_result) {
  120. return_expr = cast_expr;
  121. } else {
  122. string new_str =
  123. _return_type->prepare_return_expr(out, indent_level, cast_expr);
  124. return_expr = _return_type->get_return_expr(new_str);
  125. }
  126. } else if (_type == T_typecast) {
  127. // A regular typecast converts from a pointer type to another
  128. // pointer type. (This is different from the typecast method,
  129. // above, which converts from the concrete type to some other
  130. // type.)
  131. assert(!container.empty());
  132. string cast_expr =
  133. "(" + _return_type->get_orig_type()->get_local_name(&parser) +
  134. ")" + container;
  135. if (!convert_result) {
  136. return_expr = cast_expr;
  137. } else {
  138. string new_str =
  139. _return_type->prepare_return_expr(out, indent_level, cast_expr);
  140. return_expr = _return_type->get_return_expr(new_str);
  141. }
  142. } else if (_type == T_constructor) {
  143. // A special case for constructors.
  144. return_expr = "new " + get_call_str(container, pexprs);
  145. if (_void_return) {
  146. nout << "Error, constructor for " << *_cpptype << " returning void.\n";
  147. return_expr = "";
  148. }
  149. } else if (_type == T_assignment_method) {
  150. // Another special case for assignment operators.
  151. assert(!container.empty());
  152. InterfaceMaker::indent(out, indent_level)
  153. << get_call_str(container, pexprs) << ";\n";
  154. string this_expr = container;
  155. string ref_expr = "*" + this_expr;
  156. if (!convert_result) {
  157. return_expr = ref_expr;
  158. } else {
  159. string new_str =
  160. _return_type->prepare_return_expr(out, indent_level, ref_expr);
  161. return_expr = _return_type->get_return_expr(new_str);
  162. // Now a simple special-case test. Often, we will have converted
  163. // the reference-returning assignment operator to a pointer. In
  164. // this case, we might inadventent generate code like "return
  165. // &(*this)", when "return this" would do. We check for this here
  166. // and undo it as a special case.
  167. // There's no real good reason to do this, other than that it
  168. // feels more satisfying to a casual perusal of the generated
  169. // code. It *is* conceivable that some broken compilers wouldn't
  170. // like "&(*this)", though.
  171. if (return_expr == "&(" + ref_expr + ")" ||
  172. return_expr == "&" + ref_expr) {
  173. return_expr = this_expr;
  174. }
  175. }
  176. } else if (_void_return) {
  177. InterfaceMaker::indent(out, indent_level)
  178. << get_call_str(container, pexprs) << ";\n";
  179. } else {
  180. string call = get_call_str(container, pexprs);
  181. if (!convert_result) {
  182. return_expr = get_call_str(container, pexprs);
  183. } else {
  184. if (_return_type->return_value_should_be_simple()) {
  185. // We have to assign the result to a temporary first; this makes
  186. // it a bit easier on poor old VC++.
  187. InterfaceMaker::indent(out, indent_level);
  188. _return_type->get_orig_type()->output_instance(out, "result",
  189. &parser);
  190. out << " = " << call << ";\n";
  191. string new_str =
  192. _return_type->prepare_return_expr(out, indent_level, "result");
  193. return_expr = _return_type->get_return_expr(new_str);
  194. } else {
  195. // This should be simple enough that we can return it directly.
  196. string new_str =
  197. _return_type->prepare_return_expr(out, indent_level, call);
  198. return_expr = _return_type->get_return_expr(new_str);
  199. }
  200. }
  201. }
  202. return return_expr;
  203. }
  204. ////////////////////////////////////////////////////////////////////
  205. // Function: FunctionRemap::write_orig_prototype
  206. // Access: Public
  207. // Description: Writes a line describing the original C++ method or
  208. // function. This is generally useful only within a
  209. // comment.
  210. ////////////////////////////////////////////////////////////////////
  211. void FunctionRemap::
  212. write_orig_prototype(ostream &out, int indent_level) const {
  213. _cppfunc->output(out, indent_level, &parser, false, _num_default_parameters);
  214. }
  215. ////////////////////////////////////////////////////////////////////
  216. // Function: FunctionRemap::make_wrapper_entry
  217. // Access: Public
  218. // Description: Creates an InterrogateFunctionWrapper object
  219. // corresponding to this callable instance and stores it
  220. // in the database.
  221. ////////////////////////////////////////////////////////////////////
  222. FunctionWrapperIndex FunctionRemap::
  223. make_wrapper_entry(FunctionIndex function_index) {
  224. _wrapper_index =
  225. InterrogateDatabase::get_ptr()->get_next_index();
  226. InterrogateFunctionWrapper iwrapper;
  227. iwrapper._function = function_index;
  228. iwrapper._name = _wrapper_name;
  229. iwrapper._unique_name = _unique_name;
  230. if (output_function_names) {
  231. // If we're keeping the function names, record that the wrapper is
  232. // callable.
  233. iwrapper._flags |= InterrogateFunctionWrapper::F_callable_by_name;
  234. }
  235. Parameters::const_iterator pi;
  236. for (pi = _parameters.begin();
  237. pi != _parameters.end();
  238. ++pi) {
  239. InterrogateFunctionWrapper::Parameter param;
  240. param._parameter_flags = 0;
  241. if ((*pi)._remap->new_type_is_atomic_string()) {
  242. param._type = builder.get_atomic_string_type();
  243. } else {
  244. param._type = builder.get_type((*pi)._remap->get_new_type(), false);
  245. }
  246. param._name = (*pi)._name;
  247. if ((*pi)._has_name) {
  248. param._parameter_flags |= InterrogateFunctionWrapper::PF_has_name;
  249. }
  250. iwrapper._parameters.push_back(param);
  251. }
  252. if (_has_this) {
  253. // If one of the parameters is "this", it must be the first one.
  254. assert(!iwrapper._parameters.empty());
  255. iwrapper._parameters.front()._parameter_flags |=
  256. InterrogateFunctionWrapper::PF_is_this;
  257. }
  258. if (!_void_return) {
  259. iwrapper._flags |= InterrogateFunctionWrapper::F_has_return;
  260. }
  261. if (_return_type->new_type_is_atomic_string()) {
  262. iwrapper._return_type = builder.get_atomic_string_type();
  263. } else {
  264. iwrapper._return_type =
  265. builder.get_type(_return_type->get_new_type(), false);
  266. }
  267. if (_return_value_needs_management) {
  268. iwrapper._flags |= InterrogateFunctionWrapper::F_caller_manages;
  269. FunctionIndex destructor = _return_value_destructor;
  270. if (destructor != 0) {
  271. iwrapper._return_value_destructor = destructor;
  272. } else {
  273. // We don't need to report this warning, since the FFI code
  274. // understands that if the destructor function is zero, it
  275. // should use the regular class destructor.
  276. // nout << "Warning! Destructor for "
  277. // << *_return_type->get_orig_type()
  278. // << " is unavailable.\n"
  279. // << " Cannot manage return value for:\n "
  280. // << description << "\n";
  281. }
  282. }
  283. InterrogateDatabase::get_ptr()->add_wrapper(_wrapper_index, iwrapper);
  284. return _wrapper_index;
  285. }
  286. ////////////////////////////////////////////////////////////////////
  287. // Function: FunctionRemap::get_call_str
  288. // Access: Private
  289. // Description: Returns a string suitable for calling the wrapped
  290. // function. If pexprs is nonempty, it represents
  291. // the list of expressions that will evaluate to each
  292. // parameter value.
  293. ////////////////////////////////////////////////////////////////////
  294. string FunctionRemap::
  295. get_call_str(const string &container, const vector_string &pexprs) const {
  296. // Build up the call to the actual function.
  297. ostringstream call;
  298. // Getters and setters are a special case.
  299. if (_type == T_getter) {
  300. if (!container.empty()) {
  301. call << "(" << container << ")->" << _expression;
  302. } else {
  303. call << _expression;
  304. }
  305. } else if (_type == T_setter)
  306. {
  307. if (!container.empty()) {
  308. call << "(" << container << ")->" << _expression;
  309. } else {
  310. call << _expression;
  311. }
  312. call << " = ";
  313. _parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs));
  314. } else {
  315. if (_type == T_constructor) {
  316. // Constructors are called differently.
  317. call << _cpptype->get_local_name(&parser);
  318. } else if (_has_this && !container.empty()) {
  319. // If we have a "this" parameter, the calling convention is also
  320. // a bit different.
  321. call << "(" << container << ")->" << _cppfunc->get_local_name();
  322. } else {
  323. call << _cppfunc->get_local_name(&parser);
  324. }
  325. call << "(";
  326. int pn = _first_true_parameter;
  327. if (pn < (int)_parameters.size()) {
  328. _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
  329. pn++;
  330. while (pn < (int)_parameters.size()) {
  331. call << ", ";
  332. _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
  333. pn++;
  334. }
  335. }
  336. call << ")";
  337. }
  338. return call.str();
  339. }
  340. ////////////////////////////////////////////////////////////////////
  341. // Function: FunctionRemap::get_parameter_expr
  342. // Access: Private
  343. // Description: Returns a string that represents the expression
  344. // associated with the nth parameter. This is just the
  345. // nth element of pexprs if it is nonempty, or the name
  346. // of the nth parameter is it is empty.
  347. ////////////////////////////////////////////////////////////////////
  348. string FunctionRemap::
  349. get_parameter_expr(int n, const vector_string &pexprs) const {
  350. if (n < (int)pexprs.size()) {
  351. return pexprs[n];
  352. }
  353. return get_parameter_name(n);
  354. }
  355. ////////////////////////////////////////////////////////////////////
  356. // Function: FunctionRemap::setup_properties
  357. // Access: Private
  358. // Description: Sets up the properties of the function appropriately.
  359. // Returns true if successful, or false if there is
  360. // something unacceptable about the function.
  361. ////////////////////////////////////////////////////////////////////
  362. bool FunctionRemap::
  363. setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface_maker) {
  364. _function_signature =
  365. TypeManager::get_function_signature(_cppfunc, _num_default_parameters);
  366. _expression = ifunc._expression;
  367. if ((_ftype->_flags & CPPFunctionType::F_constructor) != 0) {
  368. _type = T_constructor;
  369. } else if ((_ftype->_flags & CPPFunctionType::F_destructor) != 0) {
  370. _type = T_destructor;
  371. } else if ((_ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) {
  372. _type = T_typecast_method;
  373. } else if ((ifunc._flags & InterrogateFunction::F_typecast) != 0) {
  374. _type = T_typecast;
  375. } else if ((ifunc._flags & InterrogateFunction::F_getter) != 0) {
  376. _type = T_getter;
  377. } else if ((ifunc._flags & InterrogateFunction::F_setter) != 0) {
  378. _type = T_setter;
  379. }
  380. if (_cpptype != (CPPType *)NULL &&
  381. ((_cppfunc->_storage_class & CPPInstance::SC_blocking) != 0)) {
  382. // If it's marked as a "blocking" method or function, record that.
  383. _blocking = true;
  384. }
  385. if (_cpptype != (CPPType *)NULL &&
  386. ((_cppfunc->_storage_class & CPPInstance::SC_static) == 0) &&
  387. _type != T_constructor) {
  388. // If this is a method, but not a static method, and not a
  389. // constructor, then we need a "this" parameter.
  390. _has_this = true;
  391. _const_method = (_ftype->_flags & CPPFunctionType::F_const_method) != 0;
  392. if (interface_maker->synthesize_this_parameter()) {
  393. // If the interface_maker demands it, the "this" parameter is treated
  394. // as any other parameter, and inserted at the beginning of the
  395. // parameter list.
  396. Parameter param;
  397. param._name = "this";
  398. param._has_name = true;
  399. param._remap = new ParameterRemapThis(_cpptype, _const_method);
  400. _parameters.push_back(param);
  401. _first_true_parameter = 1;
  402. }
  403. // Also check the name of the function. If it's one of the
  404. // assignment-style operators, flag it as such.
  405. string fname = _cppfunc->get_simple_name();
  406. if (fname == "operator =" ||
  407. fname == "operator *=" ||
  408. fname == "operator /=" ||
  409. fname == "operator %=" ||
  410. fname == "operator +=" ||
  411. fname == "operator -=" ||
  412. fname == "operator |=" ||
  413. fname == "operator &=" ||
  414. fname == "operator ^=" ||
  415. fname == "operator <<=" ||
  416. fname == "operator >>=") {
  417. _type = T_assignment_method;
  418. }
  419. }
  420. const CPPParameterList::Parameters &params =
  421. _ftype->_parameters->_parameters;
  422. for (int i = 0; i < (int)params.size() - _num_default_parameters; i++) {
  423. CPPType *type = params[i]->_type->resolve_type(&parser, _cppscope);
  424. Parameter param;
  425. param._has_name = true;
  426. param._name = params[i]->get_simple_name();
  427. if (param._name.empty()) {
  428. // If the parameter has no name, record it as being nameless,
  429. // but also synthesize one in case someone asks anyway.
  430. param._has_name = false;
  431. ostringstream param_name;
  432. param_name << "param" << i;
  433. param._name = param_name.str();
  434. }
  435. param._remap = interface_maker->remap_parameter(_cpptype, type);
  436. if (param._remap == (ParameterRemap *)NULL) {
  437. // If we can't handle one of the parameter types, we can't call
  438. // the function.
  439. return false;
  440. }
  441. param._remap->set_default_value(params[i]->_initializer);
  442. if (!param._remap->is_valid()) {
  443. return false;
  444. }
  445. _parameters.push_back(param);
  446. }
  447. if (_type == T_constructor) {
  448. // Constructors are a special case. These appear to return void
  449. // as seen by the parser, but we know they actually return a new
  450. // concrete instance.
  451. if (_cpptype == (CPPType *)NULL) {
  452. nout << "Method " << *_cppfunc << " has no struct type\n";
  453. return false;
  454. }
  455. _return_type = interface_maker->remap_parameter(_cpptype, _cpptype);
  456. if (_return_type != (ParameterRemap *)NULL) {
  457. _void_return = false;
  458. }
  459. } else if (_type == T_assignment_method) {
  460. // Assignment-type methods are also a special case. We munge
  461. // these to return *this, which is a semi-standard C++ convention
  462. // anyway. We just enforce it.
  463. if (_cpptype == (CPPType *)NULL) {
  464. nout << "Method " << *_cppfunc << " has no struct type\n";
  465. return false;
  466. } else {
  467. CPPType *ref_type = CPPType::new_type(new CPPReferenceType(_cpptype));
  468. _return_type = interface_maker->remap_parameter(_cpptype, ref_type);
  469. if (_return_type != (ParameterRemap *)NULL) {
  470. _void_return = false;
  471. }
  472. }
  473. } else {
  474. // The normal case.
  475. CPPType *rtype = _ftype->_return_type->resolve_type(&parser, _cppscope);
  476. _return_type = interface_maker->remap_parameter(_cpptype, rtype);
  477. if (_return_type != (ParameterRemap *)NULL) {
  478. _void_return = TypeManager::is_void(rtype);
  479. }
  480. }
  481. if (_return_type == (ParameterRemap *)NULL ||
  482. !_return_type->is_valid()) {
  483. // If our return type isn't something we can deal with, treat the
  484. // function as if it returns NULL.
  485. _void_return = true;
  486. _ForcedVoidReturn = true;
  487. CPPType *void_type = TypeManager::get_void_type();
  488. _return_type = interface_maker->remap_parameter(_cpptype, void_type);
  489. assert(_return_type != (ParameterRemap *)NULL);
  490. }
  491. // Do we need to manage the return value?
  492. _return_value_needs_management =
  493. _return_type->return_value_needs_management();
  494. _return_value_destructor =
  495. _return_type->get_return_value_destructor();
  496. // Should we manage a reference count?
  497. CPPType *return_type = _return_type->get_new_type();
  498. return_type = TypeManager::resolve_type(return_type, _cppscope);
  499. CPPType *return_meat_type = TypeManager::unwrap_pointer(return_type);
  500. if (manage_reference_counts &&
  501. TypeManager::is_reference_count_pointer(return_type) &&
  502. !TypeManager::has_protected_destructor(return_meat_type)) {
  503. // Yes!
  504. _manage_reference_count = true;
  505. _return_value_needs_management = true;
  506. // This is problematic, because we might not have the class in
  507. // question fully defined here, particularly if the class is
  508. // defined in some other library.
  509. _return_value_destructor = builder.get_destructor_for(return_meat_type);
  510. }
  511. return true;
  512. }