// @(#)root/reflex:$Id$ // Author: Stefan Roiser 2004 // Copyright CERN, CH-1211 Geneva 23, 2004-2006, All rights reserved. // // Permission to use, copy, modify, and distribute this software for any // purpose is hereby granted without fee, provided that this copyright and // permissions notice appear in all copies and derivatives. // // This software is provided "as is" without express or implied warranty. #ifndef REFLEX_BUILD # define REFLEX_BUILD #endif #include "FunctionMember.h" #include "Reflex/Scope.h" #include "Reflex/Object.h" #include "Reflex/internal/OwnedMember.h" #include "Reflex/DictionaryGenerator.h" #include "Function.h" #include "Reflex/Tools.h" //------------------------------------------------------------------------------- Reflex::FunctionMember::FunctionMember(const char* nam, const Type& typ, StubFunction stubFP, void* stubCtx, const char* parameters, unsigned int modifiers, TYPE memType) //------------------------------------------------------------------------------- : MemberBase(nam, typ, memType, modifiers), fStubFP(stubFP), fStubCtx(stubCtx), fParameterNames(std::vector()), fParameterDefaults(std::vector()), fReqParameters(0) { // Contruct a FunctionMember (see FunctionBuilder) UpdateFunctionParameterNames(parameters); } //------------------------------------------------------------------------------- std::string Reflex::FunctionMember::Name(unsigned int mod) const { //------------------------------------------------------------------------------- // Construct the qualified (if requested) name of the function member. std::string s; s.reserve(30); // an arbitrary, reasonable number if (0 != (mod & (QUALIFIED | Q))) { if (IsPublic()) { s += "public "; } if (IsProtected()) { s += "protected "; } if (IsPrivate()) { s += "private "; } if (IsExtern()) { s += "extern "; } if (IsStatic()) { s += "static "; } if (IsInline()) { s += "inline "; } if (IsVirtual()) { s += "virtual "; } if (IsExplicit()) { s += "explicit "; } } s += MemberBase::Name(mod); return s; } // Name /*/------------------------------------------------------------------------------- Reflex::Object Reflex::FunctionMember::Invoke( const Object & obj, const std::vector < Object > & paramList ) const { //----------------------------------------------------------------------------- if ( paramList.size() < FunctionParameterSize(true)) { throw RuntimeError("Not enough parameters given to function "); return Object(); } void * mem = CalculateBaseObject( obj ); std::vector < void * > paramValues; // needs more checking FIXME for (std::vector::const_iterator it = paramList.begin(); it != paramList.end(); ++it ) paramValues.push_back(it->Address()); return Object(TypeOf().ReturnType(), fStubFP( mem, paramValues, fStubCtx )); } */ //------------------------------------------------------------------------------- void Reflex::FunctionMember::Invoke(const Object& obj, Object* ret, const std::vector& paramList) const { //----------------------------------------------------------------------------- // Invoke this function member with object obj, return value (it it exists) // goes into Object ret. if (paramList.size() < FunctionParameterSize(true)) { throw RuntimeError("Not enough parameters given to function "); } void* mem = CalculateBaseObject(obj); static Type tVoid = Type::ByName("void"); void* retaddr = 0; if (ret && TypeOf().ReturnType() != tVoid) { retaddr = ret->Address(); } // parameters need more checking FIXME fStubFP(retaddr, mem, paramList, fStubCtx); } // Invoke /*/------------------------------------------------------------------------------- Reflex::Object Reflex::FunctionMember::Invoke( const std::vector < Object > & paramList ) const { //------------------------------------------------------------------------------- std::vector < void * > paramValues; // needs more checking FIXME for (std::vector::const_iterator it = paramList.begin(); it != paramList.end(); ++it ) paramValues.push_back(it->Address()); return Object(TypeOf().ReturnType(), fStubFP( 0, paramValues, fStubCtx )); } */ //------------------------------------------------------------------------------- void Reflex::FunctionMember::Invoke(Object* ret, const std::vector& paramList) const { //------------------------------------------------------------------------------- // Call static function, return value (it it exists) goes into Object ret. static Type tVoid = Type::ByName("void"); void* retaddr = 0; if (ret && TypeOf().ReturnType() != tVoid) { retaddr = ret->Address(); } // parameters need more checking FIXME fStubFP(retaddr, 0, paramList, fStubCtx); } //------------------------------------------------------------------------------- size_t Reflex::FunctionMember::FunctionParameterSize(bool required) const { //------------------------------------------------------------------------------- // Return number of function parameters. If required = true return number without default params. if (required) { return fReqParameters; } else { return TypeOf().FunctionParameterSize(); } } //------------------------------------------------------------------------------- void Reflex::FunctionMember::GenerateDict(DictionaryGenerator& generator) const { //------------------------------------------------------------------------------- // Generate Dictionary information about itself. std::string mName = Name(); if (mName != "__getNewDelFunctions" && mName != "__getBasesTable") { // The return type const Type& retT = TypeOf().ReturnType(); // Get function return type, register that to "used types" std::string returntype = generator.GetTypeNumber(TypeOf().ReturnType()); // Prevents __getNewDelFunctions getting into AddFunctionMember twice //if(generator.IsNewType( TypeOf() ) && Name()!="__getNewDelFunctions" ) { if (IsPrivate()) { generator.AddIntoShadow(Name(SCOPED) + "();\n"); } // Get a number for the function type //std::string number = generator.GetTypeNumber( TypeOf() ); std::stringstream temp; temp << generator.fMethodCounter; std::string number = temp.str(); ++generator.fMethodCounter; // Get current Namespace location std::string namespc = DeclaringScope().Name(SCOPED); std::stringstream tempcounter; tempcounter << generator.fMethodCounter; // Free function, shall be added into Instances-field only if (DeclaringScope().IsNamespace()) { generator.AddIntoInstances(" Type t" + tempcounter.str() + " = FunctionTypeBuilder(type_" + returntype); } else { // "normal" function, inside a class generator.AddIntoFree(".AddFunctionMember(FunctionTypeBuilder(type_" + returntype); } // Get the parameters for function for (Type_Iterator params = TypeOf().FunctionParameter_Begin(); params != TypeOf().FunctionParameter_End(); ++params) { if (DeclaringScope().IsNamespace()) { generator.AddIntoInstances(", type_" + generator.GetTypeNumber((*params))); } else { generator.AddIntoFree(", type_" + generator.GetTypeNumber((*params))); } } if (DeclaringScope().IsNamespace()) { generator.AddIntoInstances("); FunctionBuilder(t" + tempcounter.str() + ", \"" + Name() + "\", function_" + number); //function name } else { // normal function generator.AddIntoFree("), \"" + Name() + "\""); //function name } if (IsConstructor()) { generator.AddIntoFree(", constructor_"); } else if (IsDestructor()) { generator.AddIntoFree(", destructor_"); } if (IsConstructor()) { generator.AddIntoClasses("static void* constructor_"); } else if (IsDestructor()) { generator.AddIntoClasses("static void* destructor_"); } else { if (!(DeclaringScope().IsNamespace())) { generator.AddIntoFree(", method_"); generator.AddIntoClasses("\nstatic void* method_"); } else { // free function generator.AddIntoClasses("\nstatic void* function_"); } } if (!(DeclaringScope().IsNamespace())) { generator.AddIntoFree(number); //method_n } generator.AddIntoClasses(number); if (IsConstructor()) { // these have parameters generator.AddIntoClasses("(void* mem, const std::vector&"); if (FunctionParameterSize()) { generator.AddIntoClasses(" arg"); } generator.AddIntoClasses(", void*)\n{"); generator.AddIntoClasses("\n return ::new(mem) " + namespc); generator.AddIntoClasses("("); } //is constructor/destructor with parameters else if (IsDestructor()) { generator.AddIntoClasses("(void * o, const std::vector&, void *) {\n"); generator.AddIntoClasses(" ((" + namespc + "*)o)->~" + DeclaringScope().Name() + "("); } else { // method function with parameters if (DeclaringScope().IsNamespace()) { generator.AddIntoClasses(" (void*, const std::vector&"); // arg, void*)\n{"); } else { generator.AddIntoClasses(" (void* o, const std::vector&"); // arg, void*)\n{"); } if (FunctionParameterSize() > 0) { generator.AddIntoClasses(" arg"); } generator.AddIntoClasses(", void*)\n{"); if (retT.Name() != "void") { if (retT.IsFundamental()) { generator.AddIntoClasses("static " + retT.Name(SCOPED) + " ret;\n"); generator.AddIntoClasses("ret = "); } else if (retT.IsReference() || retT.IsPointer()) { generator.AddIntoClasses("return (void*)"); if (retT.IsReference()) { generator.AddIntoClasses("&"); } } else { // compound type generator.AddIntoClasses("return new " + retT.Name(SCOPED) + "("); } } if (DeclaringScope().IsNamespace()) { generator.AddIntoClasses(Name() + "( "); } else { generator.AddIntoClasses("((" + namespc + "*)o)->" + Name() + "( "); } } // Add to Stub Functions with some parameters if (FunctionParameterSize() > 0) { unsigned args = 0; // Get all parameters for (Type_Iterator methpara = TypeOf().FunctionParameter_Begin(); methpara != TypeOf().FunctionParameter_End(); ++methpara) { // get params for the function, can include pointers or references std::string param = generator.GetParams(*methpara); std::stringstream temp2; temp2 << args; // We de-deference parameter only, if it's not a pointer if (!methpara->IsPointer()) { generator.AddIntoClasses("*"); } generator.AddIntoClasses("("); //if( methpara->IsConst()) generator.AddIntoClasses("const "); std::string paraT = methpara->Name(SCOPED | QUALIFIED); if (methpara->IsReference()) { paraT = paraT.substr(0, paraT.length() - 1); } generator.AddIntoClasses(paraT); if (!methpara->IsPointer()) { generator.AddIntoClasses("*"); } generator.AddIntoClasses(") arg[" + temp2.str() + "]"); //still parameters left if ((args + 1) < FunctionParameterSize()) { generator.AddIntoClasses(", "); } ++args; //fundam } } // funct. params!=0 if (IsConstructor()) { generator.AddIntoClasses(");\n} \n"); } else { generator.AddIntoClasses(")"); if (retT.Name() == "void") { generator.AddIntoClasses(";\n return 0;\n"); } else if (retT.IsFundamental()) { generator.AddIntoClasses(";\n return & ret;\n"); } else if (retT.IsPointer() || retT.IsReference()) { generator.AddIntoClasses(";\n"); } else { // compound type generator.AddIntoClasses(");\n"); } generator.AddIntoClasses("\n} \n"); //); } if (DeclaringScope().IsNamespace()) { generator.AddIntoInstances(", 0"); } else { generator.AddIntoFree(", 0"); } if (DeclaringScope().IsNamespace()) { generator.AddIntoInstances(", \""); } else { generator.AddIntoFree(", \""); } // Get the names of the function param.types (like MyInt) if (TypeOf().FunctionParameterSize()) { unsigned dot = 0; Type_Iterator params; StdString_Iterator parnam; for (params = TypeOf().FunctionParameter_Begin(), parnam = FunctionParameterName_Begin(); params != TypeOf().FunctionParameter_End() && parnam != FunctionParameterName_End(); ++params, ++parnam) { // THESE SHOULD ALSO INCLUDE DEFAULT VALUES, // LIKE int i=5 FunctionParameterDefault_Begin(), _End // if (DeclaringScope().IsNamespace()) { generator.AddIntoInstances((*parnam)); if ((dot + 1) < FunctionParameterSize()) { generator.AddIntoInstances(";"); } } else { generator.AddIntoFree((*parnam)); if ((dot + 1) < FunctionParameterSize()) { generator.AddIntoFree(";"); } } ++dot; } } if (DeclaringScope().IsNamespace()) { generator.AddIntoInstances("\""); } else { generator.AddIntoFree("\""); } if (DeclaringScope().IsNamespace()) { // free func generator.AddIntoInstances(", "); if (IsPublic()) { generator.AddIntoInstances("PUBLIC"); } else if (IsPrivate()) { generator.AddIntoInstances("PRIVATE"); } else if (IsProtected()) { generator.AddIntoInstances("PROTECTED"); } if (IsArtificial()) { generator.AddIntoInstances(" | ARTIFICIAL"); } generator.AddIntoInstances(");\n"); ++generator.fMethodCounter; } else { generator.AddIntoFree(", "); if (IsPublic()) { generator.AddIntoFree("PUBLIC"); } else if (IsPrivate()) { generator.AddIntoFree("PRIVATE"); } else if (IsProtected()) { generator.AddIntoFree("PROTECTED"); } if (IsVirtual()) { generator.AddIntoFree(" | VIRTUAL"); } if (IsArtificial()) { generator.AddIntoFree(" | ARTIFICIAL"); } if (IsConstructor()) { generator.AddIntoFree(" | CONSTRUCTOR"); } if (IsDestructor()) { generator.AddIntoFree(" | DESTRUCTOR"); } generator.AddIntoFree(")\n"); } } } // GenerateDict //------------------------------------------------------------------------------- void Reflex::FunctionMember::UpdateFunctionParameterNames(const char* parameters) { //------------------------------------------------------------------------------- // Obtain the names and default values of the function parameters // The "real" number of parameters is obtained from the function type fParameterNames.clear(); bool hadDefaultValues = !fParameterDefaults.empty(); size_t numDefaultParams = 0; size_t type_npar = MemberBase::TypeOf().FunctionParameterSize(); std::vector params; if (parameters) { Tools::StringSplit(params, parameters, ";"); } size_t npar = std::min(type_npar, params.size()); for (size_t i = 0; i < npar; ++i) { size_t pos = params[i].find("="); fParameterNames.push_back(params[i].substr(0, pos)); if (pos != std::string::npos) { if (hadDefaultValues) { throw RuntimeError("Attempt to redefine default values of parameters!"); } else { fParameterDefaults.push_back(params[i].substr(pos + 1)); ++numDefaultParams; } } else if (!hadDefaultValues) { fParameterDefaults.push_back(""); } } // padding with blanks for (size_t i = npar; i < type_npar; ++i) { fParameterNames.push_back(""); if (!hadDefaultValues) { fParameterDefaults.push_back(""); } } if (!hadDefaultValues) { fReqParameters = type_npar - numDefaultParams; } } // UpdateFunctionParameterNames