00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "functionRemap.h"
00020 #include "typeManager.h"
00021 #include "interrogate.h"
00022 #include "parameterRemap.h"
00023 #include "parameterRemapThis.h"
00024 #include "interfaceMaker.h"
00025 #include "interrogateBuilder.h"
00026
00027 #include "interrogateDatabase.h"
00028 #include "cppInstance.h"
00029 #include "cppFunctionType.h"
00030 #include "cppParameterList.h"
00031 #include "cppReferenceType.h"
00032 #include "interrogateType.h"
00033 #include "notify.h"
00034
00035
00036
00037
00038
00039
00040 FunctionRemap::
00041 FunctionRemap(const InterrogateType &itype, const InterrogateFunction &ifunc,
00042 CPPInstance *cppfunc, int num_default_parameters,
00043 InterfaceMaker *interface) {
00044 _return_type = (ParameterRemap *)NULL;
00045 _void_return = true;
00046 _has_this = false;
00047 _first_true_parameter = 0;
00048 _num_default_parameters = num_default_parameters;
00049 _type = T_normal;
00050 _wrapper_index = 0;
00051
00052 _return_value_needs_management = false;
00053 _return_value_destructor = 0;
00054 _manage_reference_count = false;
00055
00056 _cppfunc = cppfunc;
00057 _ftype = _cppfunc->_type->as_function_type();
00058 _cpptype = itype._cpptype;
00059 _cppscope = itype._cppscope;
00060
00061 _is_valid = setup_properties(ifunc, interface);
00062 }
00063
00064
00065
00066
00067
00068
00069 FunctionRemap::
00070 ~FunctionRemap() {
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 string FunctionRemap::
00082 get_parameter_name(int n) const {
00083 ostringstream str;
00084 str << "param" << n;
00085 return str.str();
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 string FunctionRemap::
00102 call_function(ostream &out, int indent_level, bool convert_result,
00103 const string &container, const vector_string &pexprs) const {
00104 string return_expr;
00105
00106 if (_type == T_destructor) {
00107
00108 assert(!container.empty());
00109 assert(_cpptype != (CPPType *)NULL);
00110
00111 if (TypeManager::is_reference_count(_cpptype)) {
00112
00113
00114 InterfaceMaker::indent(out, indent_level)
00115 << "unref_delete(" << container << ");\n";
00116 } else {
00117 InterfaceMaker::indent(out, indent_level)
00118 << "delete " << container << ";\n";
00119 }
00120
00121 } else if (_type == T_typecast_method) {
00122
00123 string cast_expr =
00124 "(" + _return_type->get_orig_type()->get_local_name(&parser) +
00125 ")(*" + container + ")";
00126
00127 if (!convert_result) {
00128 return_expr = cast_expr;
00129 } else {
00130 string new_str =
00131 _return_type->prepare_return_expr(out, indent_level, cast_expr);
00132 return_expr = _return_type->get_return_expr(new_str);
00133 }
00134
00135 } else if (_type == T_typecast) {
00136
00137
00138
00139
00140 assert(!container.empty());
00141 string cast_expr =
00142 "(" + _return_type->get_orig_type()->get_local_name(&parser) +
00143 ")" + container;
00144
00145 if (!convert_result) {
00146 return_expr = cast_expr;
00147 } else {
00148 string new_str =
00149 _return_type->prepare_return_expr(out, indent_level, cast_expr);
00150 return_expr = _return_type->get_return_expr(new_str);
00151 }
00152
00153 } else if (_type == T_constructor) {
00154
00155 return_expr = "new " + get_call_str(container, pexprs);
00156 if (_void_return) {
00157 nout << "Error, constructor for " << *_cpptype << " returning void.\n";
00158 return_expr = "";
00159 }
00160
00161 } else if (_type == T_assignment_method) {
00162
00163 assert(!container.empty());
00164 InterfaceMaker::indent(out, indent_level)
00165 << get_call_str(container, pexprs) << ";\n";
00166
00167 string this_expr = container;
00168 string ref_expr = "*" + this_expr;
00169
00170 if (!convert_result) {
00171 return_expr = ref_expr;
00172 } else {
00173 string new_str =
00174 _return_type->prepare_return_expr(out, indent_level, ref_expr);
00175 return_expr = _return_type->get_return_expr(new_str);
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 if (return_expr == "&(" + ref_expr + ")" ||
00189 return_expr == "&" + ref_expr) {
00190 return_expr = this_expr;
00191 }
00192 }
00193
00194 } else if (_void_return) {
00195 InterfaceMaker::indent(out, indent_level)
00196 << get_call_str(container, pexprs) << ";\n";
00197
00198 } else {
00199 string call = get_call_str(container, pexprs);
00200
00201 if (!convert_result) {
00202 return_expr = get_call_str(container, pexprs);
00203
00204 } else {
00205 if (_return_type->return_value_should_be_simple()) {
00206
00207
00208 InterfaceMaker::indent(out, indent_level);
00209 _return_type->get_orig_type()->output_instance(out, "result",
00210 &parser);
00211 out << " = " << call << ";\n";
00212
00213 string new_str =
00214 _return_type->prepare_return_expr(out, indent_level, "result");
00215 return_expr = _return_type->get_return_expr(new_str);
00216
00217 } else {
00218
00219 string new_str =
00220 _return_type->prepare_return_expr(out, indent_level, call);
00221 return_expr = _return_type->get_return_expr(new_str);
00222 }
00223 }
00224 }
00225
00226 return return_expr;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236 void FunctionRemap::
00237 write_orig_prototype(ostream &out, int indent_level) const {
00238 _cppfunc->output(out, indent_level, &parser, false, _num_default_parameters);
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 FunctionWrapperIndex FunctionRemap::
00249 make_wrapper_entry(FunctionIndex function_index) {
00250 _wrapper_index =
00251 InterrogateDatabase::get_ptr()->get_next_index();
00252
00253 InterrogateFunctionWrapper iwrapper;
00254 iwrapper._function = function_index;
00255 iwrapper._name = _wrapper_name;
00256 iwrapper._unique_name = _unique_name;
00257
00258 if (true_wrapper_names) {
00259
00260
00261 iwrapper._name =
00262 InterrogateBuilder::clean_identifier(_cppfunc->get_local_name(&parser));
00263 }
00264 if (output_function_names) {
00265
00266
00267 iwrapper._flags |= InterrogateFunctionWrapper::F_callable_by_name;
00268 }
00269
00270 Parameters::const_iterator pi;
00271 for (pi = _parameters.begin();
00272 pi != _parameters.end();
00273 ++pi) {
00274 InterrogateFunctionWrapper::Parameter param;
00275 param._parameter_flags = 0;
00276 if ((*pi)._remap->new_type_is_atomic_string()) {
00277 param._type = builder.get_atomic_string_type();
00278 } else {
00279 param._type = builder.get_type((*pi)._remap->get_new_type(), false);
00280 }
00281 param._name = (*pi)._name;
00282 if ((*pi)._has_name) {
00283 param._parameter_flags |= InterrogateFunctionWrapper::PF_has_name;
00284 }
00285 iwrapper._parameters.push_back(param);
00286 }
00287
00288 if (_has_this) {
00289
00290 assert(!iwrapper._parameters.empty());
00291 iwrapper._parameters.front()._parameter_flags |=
00292 InterrogateFunctionWrapper::PF_is_this;
00293 }
00294
00295 if (!_void_return) {
00296 iwrapper._flags |= InterrogateFunctionWrapper::F_has_return;
00297 }
00298
00299 if (_return_type->new_type_is_atomic_string()) {
00300 iwrapper._return_type = builder.get_atomic_string_type();
00301 } else {
00302 iwrapper._return_type =
00303 builder.get_type(_return_type->get_new_type(), false);
00304 }
00305
00306 if (_return_value_needs_management) {
00307 iwrapper._flags |= InterrogateFunctionWrapper::F_caller_manages;
00308 FunctionIndex destructor = _return_value_destructor;
00309
00310 if (destructor != 0) {
00311 iwrapper._return_value_destructor = destructor;
00312
00313 } else {
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323 }
00324 }
00325
00326 InterrogateDatabase::get_ptr()->add_wrapper(_wrapper_index, iwrapper);
00327 return _wrapper_index;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 string FunctionRemap::
00339 get_call_str(const string &container, const vector_string &pexprs) const {
00340
00341 ostringstream call;
00342
00343
00344 if (_type == T_getter) {
00345 if (!container.empty()) {
00346 call << "(" << container << ")->" << _expression;
00347 } else {
00348 call << _expression;
00349 }
00350
00351 } else if (_type == T_setter) {
00352 if (!container.empty()) {
00353 call << "(" << container << ")->" << _expression;
00354 } else {
00355 call << _expression;
00356 }
00357
00358 call << " = ";
00359 _parameters[0]._remap->pass_parameter(call, get_parameter_expr(_first_true_parameter, pexprs));
00360
00361 } else {
00362 if (_type == T_constructor) {
00363
00364 call << _cpptype->get_local_name(&parser);
00365
00366 } else if (_has_this && !container.empty()) {
00367
00368
00369 call << "(" << container << ")->" << _cppfunc->get_local_name();
00370
00371 } else {
00372 call << _cppfunc->get_local_name(&parser);
00373 }
00374
00375 call << "(";
00376 int pn = _first_true_parameter;
00377 if (pn < (int)_parameters.size()) {
00378 _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
00379 pn++;
00380 while (pn < (int)_parameters.size()) {
00381 call << ", ";
00382 _parameters[pn]._remap->pass_parameter(call, get_parameter_expr(pn, pexprs));
00383 pn++;
00384 }
00385 }
00386 call << ")";
00387 }
00388
00389 return call.str();
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 string FunctionRemap::
00401 get_parameter_expr(int n, const vector_string &pexprs) const {
00402 if (n < (int)pexprs.size()) {
00403 return pexprs[n];
00404 }
00405 return get_parameter_name(n);
00406 }
00407
00408
00409
00410
00411
00412
00413
00414
00415 bool FunctionRemap::
00416 setup_properties(const InterrogateFunction &ifunc, InterfaceMaker *interface) {
00417 _function_signature =
00418 TypeManager::get_function_signature(_cppfunc, _num_default_parameters);
00419 _expression = ifunc._expression;
00420
00421 if ((_ftype->_flags & CPPFunctionType::F_constructor) != 0) {
00422 _type = T_constructor;
00423
00424 } else if ((_ftype->_flags & CPPFunctionType::F_destructor) != 0) {
00425 _type = T_destructor;
00426
00427 } else if ((_ftype->_flags & CPPFunctionType::F_operator_typecast) != 0) {
00428 _type = T_typecast_method;
00429
00430 } else if ((ifunc._flags & InterrogateFunction::F_typecast) != 0) {
00431 _type = T_typecast;
00432
00433 } else if ((ifunc._flags & InterrogateFunction::F_getter) != 0) {
00434 _type = T_getter;
00435
00436 } else if ((ifunc._flags & InterrogateFunction::F_setter) != 0) {
00437 _type = T_setter;
00438 }
00439
00440 if (_cpptype != (CPPType *)NULL &&
00441 ((_cppfunc->_storage_class & CPPInstance::SC_static) == 0) &&
00442 _type != T_constructor) {
00443
00444
00445
00446 _has_this = true;
00447
00448 if (interface->synthesize_this_parameter()) {
00449
00450
00451
00452 Parameter param;
00453 param._name = "this";
00454 param._has_name = true;
00455 bool is_const = (_ftype->_flags & CPPFunctionType::F_const_method) != 0;
00456 param._remap = new ParameterRemapThis(_cpptype, is_const);
00457 _parameters.push_back(param);
00458 _first_true_parameter = 1;
00459 }
00460
00461
00462
00463 string fname = _cppfunc->get_simple_name();
00464 if (fname == "operator =" ||
00465 fname == "operator *=" ||
00466 fname == "operator /=" ||
00467 fname == "operator %=" ||
00468 fname == "operator +=" ||
00469 fname == "operator -=" ||
00470 fname == "operator |=" ||
00471 fname == "operator &=" ||
00472 fname == "operator ^=" ||
00473 fname == "operator <<=" ||
00474 fname == "operator >>=") {
00475 _type = T_assignment_method;
00476 }
00477 }
00478
00479 const CPPParameterList::Parameters ¶ms =
00480 _ftype->_parameters->_parameters;
00481 for (int i = 0; i < (int)params.size() - _num_default_parameters; i++) {
00482 CPPType *type = params[i]->_type->resolve_type(&parser, _cppscope);
00483 Parameter param;
00484 param._has_name = true;
00485 param._name = params[i]->get_simple_name();
00486
00487 if (param._name.empty()) {
00488
00489
00490 param._has_name = false;
00491 ostringstream param_name;
00492 param_name << "param" << i;
00493 param._name = param_name.str();
00494 }
00495
00496 param._remap = interface->remap_parameter(_cpptype, type);
00497 if (param._remap == (ParameterRemap *)NULL) {
00498
00499
00500 return false;
00501 }
00502 param._remap->set_default_value(params[i]->_initializer);
00503
00504 if (!param._remap->is_valid()) {
00505 return false;
00506 }
00507
00508 _parameters.push_back(param);
00509 }
00510
00511 if (_type == T_constructor) {
00512
00513
00514
00515
00516 if (_cpptype == (CPPType *)NULL) {
00517 nout << "Method " << *_cppfunc << " has no struct type\n";
00518 return false;
00519 }
00520
00521 _return_type = interface->remap_parameter(_cpptype, _cpptype);
00522 if (_return_type != (ParameterRemap *)NULL) {
00523 _void_return = false;
00524 }
00525
00526 } else if (_type == T_assignment_method) {
00527
00528
00529
00530
00531 if (_cpptype == (CPPType *)NULL) {
00532 nout << "Method " << *_cppfunc << " has no struct type\n";
00533 return false;
00534 } else {
00535 CPPType *ref_type = CPPType::new_type(new CPPReferenceType(_cpptype));
00536 _return_type = interface->remap_parameter(_cpptype, ref_type);
00537 if (_return_type != (ParameterRemap *)NULL) {
00538 _void_return = false;
00539 }
00540 }
00541
00542 } else {
00543
00544 CPPType *rtype = _ftype->_return_type->resolve_type(&parser, _cppscope);
00545 _return_type = interface->remap_parameter(_cpptype, rtype);
00546 if (_return_type != (ParameterRemap *)NULL) {
00547 _void_return = TypeManager::is_void(rtype);
00548 }
00549 }
00550
00551 if (_return_type == (ParameterRemap *)NULL ||
00552 !_return_type->is_valid()) {
00553
00554
00555 _void_return = true;
00556 CPPType *void_type = TypeManager::get_void_type();
00557 _return_type = interface->remap_parameter(_cpptype, void_type);
00558 assert(_return_type != (ParameterRemap *)NULL);
00559 }
00560
00561
00562 _return_value_needs_management =
00563 _return_type->return_value_needs_management();
00564 _return_value_destructor =
00565 _return_type->get_return_value_destructor();
00566
00567
00568 CPPType *return_type = _return_type->get_new_type();
00569 CPPType *return_meat_type = TypeManager::unwrap_pointer(return_type);
00570
00571 if (manage_reference_counts &&
00572 TypeManager::is_reference_count_pointer(return_type) &&
00573 !TypeManager::has_protected_destructor(return_meat_type)) {
00574
00575 _manage_reference_count = true;
00576 _return_value_needs_management = true;
00577
00578
00579
00580
00581 _return_value_destructor = builder.get_destructor_for(return_meat_type);
00582 }
00583
00584 return true;
00585 }