00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020
00021 #include "EDoc/FunctionType.h"
00022 #include "EDoc/PersistenceIFace.h"
00023 #include "EDoc/Dictionary.h"
00024 #include "EDoc/exceptions.h"
00025 #include "EDoc/Logger.h"
00026 #include "EDoc/utils.h"
00027 #include "EDoc/PStack.h"
00028 #include "EDoc/StackRef.h"
00029
00030 #include "EDoc/Type.h"
00031 #include "EDoc/Function.h"
00032 #include "EDoc/NotificationIFace.h"
00033
00034 #include "EDoc/persistence_data.h"
00035 #include "IndexedDictionary.h"
00036
00037 #include <iostream>
00038
00039
00040
00041
00042 #define EDOC_MERGE_ERROR(Message) \
00043 EDOC_Error(Message); \
00044 EDOC_THROW_EXCEPTION(MergeException, \
00045 "Failed merging function type.", Message);
00046
00047
00048 namespace EDoc
00049 {
00050
00051 uint8_t FunctionType::GetRecordType() const
00052 {
00053 return VALUE_RECORD_TYPE_FUNCTION_TYPE;
00054 }
00055
00056 FunctionType::FunctionType(Dictionary& dict_in, std::string key_name_in) :
00057 StringIdentifiedObject(dict_in, key_name_in),
00058 return_type(NULL),
00059 method_context(NULL),
00060 is_const(false),
00061 has_exception_spec(false)
00062 {
00063 }
00064
00065 FunctionType::FunctionType(Dictionary& dict_in, int32_t index_in) :
00066 StringIdentifiedObject(dict_in, index_in),
00067 return_type(NULL),
00068 method_context(NULL),
00069 is_const(false),
00070 has_exception_spec(false)
00071 {
00072 }
00073
00074 FunctionType& FunctionType::operator=(const FunctionType& right)
00075 {
00076
00077 if (this == &right)
00078 {
00079 EDOC_Finer("Not assigning as the instances are the same.");
00080 return *this;
00081 }
00082
00083 full_name = right.full_name;
00084 return_type = dict.types.AlwaysGet(*right.return_type);
00085 method_context = NULL;
00086 if (right.method_context)
00087 {
00088 method_context = dict.types.AlwaysGet(*right.method_context);
00089 }
00090
00091 Erase(parameters);
00092 for (size_t i = 0; i < right.parameters.size(); i++)
00093 {
00094 parameters.push_back(
00095 dict.types.AlwaysGet(*right.parameters[i]));
00096 }
00097
00098 is_const = right.is_const;
00099
00100 has_exception_spec = right.has_exception_spec;
00101 Erase(exception_spec);
00102 for (size_t i = 0; i < right.exception_spec.size(); i++)
00103 {
00104 exception_spec.push_back(
00105 dict.types.AlwaysGet(*right.exception_spec[i]));
00106 }
00107
00108 populated = right.populated;
00109 return *this;
00110 }
00111
00112 void FunctionType::Read(PersistenceIFace& file, IndexedDictionary& idict)
00113 {
00114 size_t size = 0;
00115
00116 full_name = file.ReadString(KEY_FULL_NAME);
00117 return_type = idict.types.AlwaysGet(file.ReadUInt32(KEY_RETURN_TYPE));
00118 is_const = file.ReadBoolean(KEY_IS_CONST);
00119
00120 method_context = NULL;
00121 if (file.ReadBoolean(KEY_IS_METHOD))
00122 {
00123 method_context = idict.types.AlwaysGet(
00124 file.ReadUInt32(KEY_METHOD_CONTEXT));
00125 }
00126
00127 size = file.ReadUInt32(KEY_PARAMETERS_LS);
00128 for (size_t i = 0; i < size; i++)
00129 {
00130 exception_spec.push_back(
00131 idict.types.AlwaysGet(file.ReadUInt32(KEY_PARAMETERS_LI)));
00132 }
00133
00134
00135 Erase(exception_spec);
00136 has_exception_spec = file.ReadBoolean(KEY_HAS_EXCEPTION_SPEC);
00137 if (has_exception_spec)
00138 {
00139 size = file.ReadUInt32(KEY_EXCEPTION_SPEC_LS);
00140 for (size_t i = 0; i < size; i++)
00141 {
00142 exception_spec.push_back(
00143 idict.types.AlwaysGet(file.ReadUInt32(KEY_EXCEPTION_SPEC_LI)));
00144 }
00145 }
00146
00147 populated = true;
00148 SetKeyName(full_name);
00149 }
00150
00151 void FunctionType::Write(PersistenceIFace& file) const
00152 {
00153 file.WriteString(KEY_FULL_NAME, full_name);
00154 file.WriteUInt32(KEY_RETURN_TYPE, return_type->GetIndex());
00155 file.WriteBoolean(KEY_IS_CONST, is_const);
00156
00157 file.WriteBoolean(KEY_IS_METHOD, method_context);
00158 if (method_context)
00159 {
00160 file.WriteUInt32(KEY_METHOD_CONTEXT, method_context->GetIndex());
00161 }
00162
00163 file.WriteUInt32(KEY_PARAMETERS_LS, exception_spec.size());
00164 for (size_t i = 0; i < exception_spec.size(); i++)
00165 {
00166 file.WriteUInt32(KEY_PARAMETERS_LI, exception_spec[i]->GetIndex());
00167 }
00168
00169
00170 file.WriteBoolean(KEY_HAS_EXCEPTION_SPEC, has_exception_spec);
00171 if (has_exception_spec)
00172 {
00173 file.WriteUInt32(KEY_EXCEPTION_SPEC_LS, exception_spec.size());
00174 for (size_t i = 0; i < exception_spec.size(); i++)
00175 {
00176 file.WriteUInt32(KEY_EXCEPTION_SPEC_LI,
00177 exception_spec[i]->GetIndex());
00178 }
00179 }
00180 }
00181
00182 std::ostream& FunctionType::Print(std::ostream& out, std::string prefix) const
00183 {
00184 out << prefix << "Name: " << full_name << std::endl;
00185 out << prefix << "Return Type: " << return_type->GetDeclaredName()
00186 << std::endl;
00187 if (method_context)
00188 {
00189 out << prefix << "Method Context: "
00190 << method_context->GetDeclaredName() << std::endl;
00191 }
00192
00193 for (size_t i = 0; i < parameters.size(); i++)
00194 {
00195 out << prefix << "Parameter: " << parameters[i]->GetDeclaredName()
00196 << std::endl;
00197 }
00198
00199 if (is_const)
00200 {
00201 out << prefix << "Is Const: True" << std::endl;
00202 }
00203 else
00204 {
00205 out << prefix << "Is Const: False" << std::endl;
00206 }
00207
00208 if (has_exception_spec)
00209 {
00210 out << prefix << "Has Throw Spec: True" << std::endl;
00211 out << "Throw spec: " << GetSpecString() << std::endl;
00212 }
00213 else
00214 {
00215 out << prefix << "Has Throw Spec: False" << std::endl;
00216 }
00217
00218 return out;
00219 }
00220
00221 void FunctionType::Merge(const StringIdentifiedObject& right_in)
00222 {
00223 const FunctionType& right(dynamic_cast<const FunctionType&>(right_in));
00224
00225 if (!populated)
00226 {
00227 *this = right;
00228 return;
00229 }
00230
00231 if (full_name != right.full_name)
00232 {
00233 EDOC_MERGE_ERROR("Unable to merge two function types with "
00234 "different names. "
00235 "Left: " << full_name << ", right: " << right.full_name);
00236 }
00237
00238 if (return_type->GetNormalisedName() !=
00239 right.return_type->GetNormalisedName())
00240 {
00241 EDOC_MERGE_ERROR("Unable to merge two function types @@@");
00242 }
00243
00244 if ((method_context && !right.method_context) ||
00245 (!method_context && right.method_context))
00246 {
00247 EDOC_MERGE_ERROR("Unable to merge two function types @@@");
00248 }
00249 else if (method_context && right.method_context)
00250 {
00251 if (method_context->GetNormalisedName() !=
00252 right.method_context->GetNormalisedName())
00253 {
00254 EDOC_MERGE_ERROR("Unable to merge two function types @@@");
00255 }
00256 }
00257
00258 if (parameters.size() != right.parameters.size())
00259 {
00260 EDOC_MERGE_ERROR("Unable to merge two function types @@@");
00261 }
00262
00263 for (size_t i = 0; i < parameters.size(); i++)
00264 {
00265 if (parameters[i]->GetNormalisedName() !=
00266 right.parameters[i]->GetNormalisedName())
00267 {
00268 EDOC_MERGE_ERROR("Unable to merge two function types @@@");
00269 }
00270 }
00271
00272 if (is_const != right.is_const)
00273 {
00274 EDOC_MERGE_ERROR("Unable to merge two function types @@@");
00275 }
00276
00277
00278
00279
00280 bool exception_specs_differ = false;
00281 if (has_exception_spec != right.has_exception_spec)
00282 {
00283 exception_specs_differ = true;
00284 }
00285
00286
00287 if (!exception_specs_differ &&
00288 (exception_spec.size() != right.exception_spec.size()))
00289 {
00290 exception_specs_differ = true;
00291 }
00292 for (size_t i = 0; !exception_specs_differ && (i < exception_spec.size());
00293 i++)
00294 {
00295 bool found = false;
00296 for (size_t j = 0; j < right.exception_spec.size(); j++)
00297 {
00298 if (right.exception_spec[j]->GetNormalisedName() ==
00299 exception_spec[i]->GetNormalisedName())
00300 {
00301 found = true;
00302 break;
00303 }
00304 }
00305
00306 if (!found)
00307 {
00308 exception_specs_differ = true;
00309 }
00310 }
00311
00312
00313 if (exception_specs_differ)
00314 {
00315 EDOC_NOTIFICATION(WDIFF_THROW,
00316 "Function: " << GetKeyName()
00317 << ", Declared Name: " << GetDeclaredName()
00318 << ", Left Spec: " << GetSpecString()
00319 << ", Right Spec: " << right.GetSpecString(),
00320 NULL, NULL, 0, NULL, 0, NULL, NULL, this, NULL)
00321
00322
00323
00324
00325
00326
00327 EDOC_Warning("Merging two functions with different exception specs."
00328 << "\nLeft Spec: " << GetSpecString()
00329 << "\nRight Spec: " << right.GetSpecString()
00330 << "\nFunction Name: " << GetKeyName());
00331
00332 has_exception_spec = true;
00333 std::vector<Type*> merged_spec;
00334
00335
00336 for (size_t i = 0; i < exception_spec.size(); i++)
00337 {
00338 bool found = false;
00339 for (size_t j = 0; j < right.exception_spec.size(); j++)
00340 {
00341 if (right.exception_spec[j]->GetNormalisedName() ==
00342 exception_spec[i]->GetNormalisedName())
00343 {
00344 found = true;
00345 break;
00346 }
00347 }
00348
00349 if (found)
00350 {
00351 merged_spec.push_back(exception_spec[i]);
00352 }
00353 }
00354 exception_spec = merged_spec;
00355
00356 EDOC_Warning("Resulting merged spec is: " << GetSpecString());
00357 }
00358
00359 }
00360
00361 std::string FunctionType::GetSpecString() const
00362 {
00363 std::ostringstream stream;
00364
00365 if (has_exception_spec)
00366 {
00367 stream << "throws(";
00368 for (size_t i = 0; i < exception_spec.size(); i++)
00369 {
00370 if (i != 0)
00371 {
00372 stream << ", ";
00373 }
00374 if (exception_spec[i]->IsPopulated())
00375 {
00376 stream << exception_spec[i]->GetDeclaredName();
00377 }
00378 else
00379 {
00380 stream << "(UNPOPULATED: " << exception_spec[i]->GetKeyName()
00381 <<")";
00382 }
00383 }
00384 stream << ")";
00385 }
00386
00387 return stream.str();
00388 }
00389
00390 bool FunctionType::IsEquivilant(const FunctionType& right) const
00391 {
00392 if (this == &right)
00393 {
00394 return true;
00395 }
00396
00397
00398 if (!return_type->IsEquivilant(*right.return_type))
00399 {
00400 return false;
00401 }
00402
00403
00404 if (parameters.size() != right.parameters.size())
00405 {
00406 return false;
00407 }
00408
00409
00410 for (size_t i = 0; i < parameters.size(); i++)
00411 {
00412 if (!parameters[i]->IsEquivilant(*right.parameters[i]))
00413 {
00414 return false;
00415 }
00416 }
00417
00418
00419
00420 return true;
00421 }
00422
00423
00424 #define EDOC_REPLACE(DataFunctionType, Data, From, To, Count) \
00425 if ((void*)Data == From) {Data = (DataFunctionType*)To; Count++;}
00426
00427 size_t FunctionType::ReplaceReferences(PStack& stack, void* remove,
00428 void* replace)
00429 {
00430 size_t count = 0;
00431 if (!stack.Push(this))
00432 {
00433 return count;
00434 }
00435
00436 EDOC_REPLACE(Type, return_type, remove, replace, count);
00437 EDOC_REPLACE(Type, method_context, remove, replace, count);
00438
00439 for (size_t i = 0; i < parameters.size(); i++)
00440 {
00441 EDOC_REPLACE(Type, parameters[i], remove, replace, count);
00442 }
00443
00444 for (size_t i = 0; i < exception_spec.size(); i++)
00445 {
00446 EDOC_REPLACE(Type, exception_spec[i], remove, replace, count);
00447 }
00448
00449 for (size_t i = 0; i < addressed_functions.size(); i++)
00450 {
00451 EDOC_REPLACE(Function, addressed_functions[i], remove, replace, count);
00452 }
00453
00454 return count;
00455 }
00456
00457 void FunctionType::Validate(PStack& stack, const Dictionary& dict_in) const
00458 {
00459
00460
00461
00462 StackRef ref(stack, this);
00463 if (!ref)
00464 {
00465 return;
00466 }
00467
00468 EDOC_ASSERT(&dict == &dict_in,
00469 "Current dict: " << &dict
00470 << "\nRequired dict: " << &dict_in
00471 << "\nKey: " << key_name
00472 << "\nIndex: " << index);
00473 EDOC_ASSERT(populated, "");
00474 EDOC_ASSERT(dict_in.function_types.Get(GetKeyName()) == this,
00475 "Our address: " << (const void*)this
00476 << ", dicts address: "
00477 << (const void*)dict_in.function_types.Get(GetKeyName())
00478 << " type: " << *this
00479 << " types scoped name: " << GetKeyName());
00480
00481 EDOC_ASSERT(return_type, *this);
00482 return_type->Validate(stack, dict_in);
00483
00484 if (method_context)
00485 {
00486 method_context->Validate(stack, dict_in);
00487 }
00488
00489 for (size_t i = 0; i < parameters.size(); i++)
00490 {
00491 EDOC_ASSERT(parameters[i], *this);
00492 parameters[i]->Validate(stack, dict_in);
00493 }
00494
00495
00496
00497 if (!has_exception_spec)
00498 {
00499 EDOC_ASSERT(exception_spec.size() == 0, "");
00500 }
00501
00502 for (size_t i = 0; i < exception_spec.size(); i++)
00503 {
00504 EDOC_ASSERT(exception_spec[i], *this);
00505 exception_spec[i]->Validate(stack, dict_in);
00506 }
00507
00508
00509 for (size_t i = 0; i < addressed_functions.size(); i++)
00510 {
00511 EDOC_ASSERT(addressed_functions[i], *this);
00512 addressed_functions[i]->Validate(stack, dict_in);
00513 }
00514 }
00515
00516 std::string FunctionType::GetNameInternal(bool canonical) const
00517 {
00518 if (!canonical)
00519 {
00520 return full_name;
00521 }
00522 else
00523 {
00524
00525 std::ostringstream stream;
00526
00527 stream << return_type->GetNormalisedName() << " (";
00528 if (method_context)
00529 {
00530 stream << method_context->GetNormalisedName() << "::";
00531 }
00532 stream << "*)(";
00533 for (size_t i = 0; i < parameters.size(); i++)
00534 {
00535 if (i == 0)
00536 {
00537 stream << parameters[i]->GetNormalisedName();
00538 }
00539 stream << ", " << parameters[i]->GetNormalisedName();
00540 }
00541 stream << ")";
00542
00543
00544 return stream.str();
00545 }
00546 }
00547
00548
00549 }