// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- // // Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany. // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public License (LGPL). // // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // License ACDK-FreeLicense document enclosed in the distribution // for more for more details. // This file is part of the Artefaktur Component Development Kit: // ACDK // // Please refer to // - http://www.acdk.de // - http://www.artefaktur.com // - http://acdk.sourceforge.net // for more information. // // $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/dmi/StdDispatch.cpp,v 1.98 2005/04/18 15:14:27 kommer Exp $ #include <acdk.h> #include <acdk/lang/NoSuchDmiElementException.h> #include <acdk/lang/ParamsMismatchException.h> #include <acdk/lang/ClassNotFoundException.h> #include <acdk/lang/NoSuchFieldException.h> #include <acdk/lang/NoSuchMethodException.h> #include <acdk/lang/Number.h> #include <acdk/lang/Integer.h> #include <acdk/lang/Character.h> #include <acdk/lang/DmiTypeConversionException.h> #include "DmiNamedArg.h" #include "ClazzInfo.h" #include "ClazzAttributesRes.h" namespace acdk { namespace lang { namespace dmi { //virtual DmiClient& StdDispatch::getDmiClient() { return AcdkDmiClient::getDmiClient(); } //inline ::acdk::lang::Object* StdDispatch::getDmiTarget(const ::acdk::lang::dmi::ClazzInfo*& ci) { bool bret = false; ::acdk::lang::Object* o = (::acdk::lang::Object*)this; while ((o = o->getDmiTarget(bret, ci)) && bret == true) ; return o; } //static const ClazzMethodInfo* StdDispatch::_invoke_notexistant( ::acdk::lang::Object* This, IN(acdk::lang::RString) fname, ScriptVar& ret, ScriptVarArray& args, DmiClient& dc, IN(::acdk::lang::RStringArray) namedArgs, int flags, const ClazzInfo* clazzinfo, const ClazzMethodInfo* methinf) { THROW1(UnsupportedOperationException, "No DMI function available for call"); return 0; } //static const ClazzMethodInfo* StdDispatch::_invoke_dynamic( ::acdk::lang::Object* This, IN(acdk::lang::RString) fname, ScriptVar& ret, ScriptVarArray& args, DmiClient& dc, IN(::acdk::lang::RStringArray) namedArgs, int flags, const ClazzInfo* clazzinfo, const ClazzMethodInfo* methinf) { if (clazzinfo == 0) clazzinfo = This->getClazzInfo(); if ((flags & MiIvNoWeakBind) == 0 && This != 0) { bool __forward = false; ::acdk::lang::Object* __forwardPtr = This->_getObjectPtr()->getDmiTarget(__forward, clazzinfo); if (__forward == true) return __forwardPtr->standardDispatch(fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf); } DmiClient::setCurInvokeFlags(flags); // because on circumstance the flags are not deleted if (methinf == 0 || flags & MiIvViaHash) { const ClazzInfo* clazzsic = clazzinfo; methinf = ::acdk::lang::dmi::StdDispatch::lookupMethod(clazzinfo, fname, args, namedArgs, dc, flags, methinf); flags &= ~MiIvViaHash; } return methinf->dispatch(This, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf); //return clazzinfo->dynamic_dispatch(This, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf); } //static const ClazzMethodInfo* StdDispatch::_invoke_dynamic_super( ::acdk::lang::Object* This, IN(acdk::lang::RString) fname, ScriptVar& ret, ScriptVarArray& args, DmiClient& dc, IN(::acdk::lang::RStringArray) namedArgs, int flags, const ClazzInfo* clazzinfo, const ClazzMethodInfo* methinf) { /* if (methinf == 0) { const ClazzInfo* clazzsic = clazzinfo; methinf = ::acdk::lang::dmi::StdDispatch::lookupMethod(clazzinfo, fname, args, namedArgs, dc, flags); if (clazzsic != clazzinfo) return clazzinfo->dynamic_dispatch(This, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf); } int i; for (i = 0; i < clazzinfo->getInterfacesCount(); ++i) { const ClazzInfo* ci = clazzinfo->interfaces[i]->type; methinf = ci->dynamic_dispatch(This, fname, ret, args, dc, namedArgs, flags, ci, methinf); if (methinf != 0) break; }*/ return methinf; } //static const ClazzMethodInfo* StdDispatch::_invoke_static( IN(acdk::lang::RString) fname, ScriptVar& ret, ScriptVarArray& args, DmiClient& dc, IN(::acdk::lang::RStringArray) namedArgs, int flags, const ClazzInfo* clazzinfo, const ClazzMethodInfo* methinf) { const ClazzInfo* clazzSic = clazzinfo; if (methinf == 0 || flags & MiIvViaHash) { methinf = ::acdk::lang::dmi::StdDispatch::lookupMethod(clazzinfo, fname, args, namedArgs, dc, flags, methinf); flags &= ~MiIvViaHash; } if (clazzSic->isArray() == true) { clazzinfo = clazzSic; ASCLITERAL(GetClass); if (fname->equals(lit_GetClass) == true) { ret = inOf(Class::getSingeltonClass(clazzinfo)); return methinf; } } if (methinf->dispatch == 0) THROW1(NoSuchMethodException, "Method has no DMI implementation (probably abstract class): " + clazzinfo->toTypeString() + "::" + methinf->name); // ### check if methinf is this methinf = methinf->dispatch(0, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf); return methinf; } //static const ClazzMethodInfo* StdDispatch::_invoke_static_super( IN(acdk::lang::RString) fname, ScriptVar& ret, ScriptVarArray& args, DmiClient& dc, IN(::acdk::lang::RStringArray) namedArgs, int flags, const ClazzInfo* clazzinfo, const ClazzMethodInfo* methinf) { /* int i; for (i = 0; i < clazzinfo->getInterfacesCount(); ++i) { const ClazzInfo* ci = clazzinfo->interfaces[i]->type; methinf = ci->static_dispatch(fname, ret, args, dc, namedArgs, flags, ci, methinf); if (methinf != 0) break; }*/ return methinf; } //virtual const ClazzMethodInfo* StdDispatch::standardDispatch( IN(acdk::lang::RString) fname, ScriptVar& ret, ScriptVarArray& args, DmiClient& dc, IN(::acdk::lang::RStringArray) namedArgs/* = Nil*/, int flags, const ClazzInfo* clazzinfo, const ClazzMethodInfo* methinf/* = 0*/) { if (clazzinfo == 0) clazzinfo = getClazzInfo(); clazzinfo = clazzinfo->loadFullClazzInfo(); DmiClient::setCurInvokeFlags(flags); return clazzinfo->dynamic_dispatch((acdk::lang::Object*)this, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf); /* not correct, because __dmi_proxy_target should not be static ::acdk::lang::dmi::ClazzInfo* ci = getClazzInfo(); KeyValue<StringRes, ClazzAttributeResValue> kv = ClazzAttributesRes::getAttribute((MetaInfo*)ci, "__dmi_proxy_target"); if (kv.value.data != 0) { acdk::lang::Object fw = (acdk::lang::Object*)kv.value.data; return fw->standardDispatch(fname, ret, args, dc, namedArgs, flags, methinf); } */ THROW1(UnsupportedOperationException, "StdDispatch::standardDispatch"); return 0; } /** This version of StandardDispatch is used in the generated stub */ //static const ClazzMethodInfo* StdDispatch::StandardDispatch(IN(acdk::lang::RString) fname, ScriptVar& ret, ScriptVarArray& args, DmiClient& dc, IN(::acdk::lang::RStringArray) namedArgs, int flags, const ClazzInfo* clazzinfo, const ClazzMethodInfo* methinf) { /* if (clazzinfo == 0) clazzinfo = getClazzInfo(); */ clazzinfo = clazzinfo->loadFullClazzInfo(); return clazzinfo->static_dispatch(fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf); THROW1(UnsupportedOperationException, "StdDispatch::standardDispatch: This method is reserved for the generated stub"); return 0; } //static const ClazzMethodInfo* StdDispatch::StandardDispatch( IN(acdk::lang::RString) classname, IN(acdk::lang::RString) fname , ScriptVar& ret , ScriptVarArray& args , DmiClient& dc , IN(::acdk::lang::RStringArray) namedArgs , int flags , const ClazzInfo* clazzinfo , const ClazzMethodInfo* methinf/* = 0*/) { RClass cls; cls = Class::forName(&classname);// method with use cstr instead of RString const ClazzInfo* ci = cls->objectClazzInfo(); if (clazzinfo == 0) clazzinfo = ci; ci = ci->loadFullClazzInfo(); if (ci->static_dispatch != 0/* && namedArgs == Nil*/) return ci->static_dispatch(fname, ret, args, dc, namedArgs, flags, ci, methinf); const ClazzMethodInfo* mi = lookupMethod(ci, fname, args, namedArgs, dc, flags, methinf); if (mi->dispatch != 0) return mi->dispatch(0, fname, ret, args, dc, namedArgs, flags, ci, mi); return _invoke_notexistant(0, fname, ret, args, dc, namedArgs, flags, ci, mi); } void throwFieldNotFount(IN(RString) msg, const ClazzInfo* ci, const ClazzFieldInfo* fi, int formatFlags) { StringBuffer sb; sb.append(msg); sb.append(MetaInfo::flagsToString(MetaInfo::accessMask(fi->flags) | MetaInfo::staticMask(fi->flags), FieldInfoExtFlags(0))); sb.append(" "); ci->toTypeString(sb, formatFlags); sb.append("::"); sb.append(fi->name); THROW1(NoSuchFieldException, sb.toString()); } //static ScriptVar StdDispatch::_getMember(::acdk::lang::Object* This, const ClazzInfo* clazz, const ClazzFieldInfo* field, IN(acdk::lang::RString) fieldname, DmiClient& dc, int flags) { if (field->accessor != 0) { ScriptVar erg; field->accessor(This, fieldname, erg, dc, flags | MiReadOnly, clazz, field); return erg; } if ((flags & MiIvNoThrowIfNotFound) == 0) throwFieldNotFount("Field has no accessor function", clazz, field, dc._formatFlags); return ScriptVar(); } //static void StdDispatch::_setMember(::acdk::lang::Object* This, const ScriptVar& val, const ClazzInfo* clazz, const ClazzFieldInfo* field, IN(acdk::lang::RString) fieldname, DmiClient& dc, int flags) { if (field->accessor != 0) { field->accessor(This, fieldname, const_cast<ScriptVar&>(val), dc, flags & ~MiReadOnly, clazz, field); return; } if ((flags & MiIvNoThrowIfNotFound) == 0) throwFieldNotFount("Field has no accessor function", clazz, field, dc._formatFlags); } //static dmi::ScriptVar StdDispatch::getStaticMember(const ClazzInfo* clazz, IN(acdk::lang::RString) fieldname, DmiClient& dc, int flags , const ClazzInfo* type_requested) { //int mflags = Modifier_accessMask(flags) | Modifier_accessMask(flags); if (clazz->flags & MiCiWeakBind && (flags & MiIvNoWeakBind) == 0) { ScriptVar ret; ScriptVarArray args(1); args[0] = &fieldname; clazz->static_dispatch("peek_static", ret, args, dc, Nil, flags, clazz, 0); return ret; } const ClazzFieldInfo* field = ClazzInfo::findField(clazz, fieldname, flags); ScriptVar sv = _getMember(0, clazz, field, fieldname, dc, flags); dc.castTo(sv, type_requested); return sv; //return ScriptVar_dynConvert(sv, type_requested); } dmi::ScriptVar StdDispatch::getMember(IN(RString) fieldname, DmiClient& dc, int flags, const ClazzInfo* type_requested) { //acdk::lang::Object* This = this; //dynamic_cast<ObjectBase*>(this)->_cast(Object::clazzInfo()); bool forwarded = false; const ClazzInfo* clazz = 0; acdk::lang::Object* This = this->getDmiTarget(forwarded, clazz); if (clazz == 0) clazz = This->getClazzInfo(); const ClazzInfo* tclazz = clazz; clazz = clazz->loadFullClazzInfo(); if ((clazz->flags & MiCiWeakBind) && (flags & MiIvNoWeakBind) == 0) { ScriptVar ret; ScriptVarArray args(1); args[0] = &fieldname; /* if (flags & MiPublic) mflags |= MiPublic; */ This->standardDispatch("peek", ret, args, dc, Nil, flags, clazz, 0); return ret; } const ClazzFieldInfo* fi = ClazzInfo::findField(clazz, fieldname, flags); ScriptVar sv = _getMember(This, clazz, fi, fieldname, dc, flags); if (type_requested == 0) return sv; if (dc.typeDistance(sv, type_requested) == -1) { StringBuffer sb("Cannot convert variable: "); sb.append(sv.toString()); sb.append(" to type "); type_requested->toTypeString(sb, dc._formatFlags); sb.append(" in accessing "); fi->toTypeString(sb, dc._formatFlags); if ((flags & MiIvNoThrowIfNotFound) == 0) THROW1(DmiTypeConversionException, sb.toString()); return ScriptVar(); } dc.castTo(sv, type_requested); return sv; } void StdDispatch::setMember(IN(RString) fieldname, const ScriptVar& newval, DmiClient& dc, int flags) { bool forwarded = false; //const ClazzInfo* clazz = This->getClazzInfo(); acdk::lang::Object* This = dmi_cast<acdk::lang::Object>((acdk::lang::Object*)this); const ClazzInfo* clazz = 0; This = This->getDmiTarget(forwarded, clazz); if (clazz == 0) clazz = This->getClazzInfo(); clazz = clazz->loadFullClazzInfo(); if (getClazzInfo()->flags & MiCiWeakBind) { ScriptVar ret; ScriptVarArray args(2); args[0] = &fieldname; args[1] = newval; /* if (flags & MiPublic) mflags |= MiPublic; */ This->standardDispatch("poke", ret, args, dc, Nil, flags, getClazzInfo(), 0); return; } const ClazzFieldInfo* fi = ClazzInfo::findField(clazz, fieldname, flags); ScriptVar sv = newval; dc.castTo(sv, fi->type); _setMember(This, sv, clazz, fi, fieldname, dc, flags); } SysFields StdDispatch::getInternalFields(int flags, const ClazzInfo* clazz) { // #### TODO handle basic/ObjectArray if (clazz == 0) clazz = getClazzInfo(); clazz = clazz->loadFullClazzInfo(true, false); if (clazz == 0) return SysFields(0); ClazzFieldInfoVec fds; clazz->getFields(fds, flags); SysFields sf(fds.size()); acdk::lang::Object* This = dynamic_cast<acdk::lang::Object*>(this); DmiClient& dc = AcdkDmiClient::getDmiClient(); for (int i = 0; i < fds.size(); ++i) { ScriptVar sv; const ClazzFieldInfo* fi = fds[i]; if (fi->accessor != 0) { fi->accessor(This, fi->name, sv, dc, MiReadOnly | MiAiOut, (const ClazzInfo*)fi->_scopeParent, fi); // ### TODO missing here an else? sf[i] = SysField::getField(fi, sv); } } return sf; } SysField StdDispatch::getInternalField(IN(RString) name, int flags, const ClazzInfo* ci) { if (ci == 0) ci = getClazzInfo(); ci = ci->loadFullClazzInfo(true, false); if (ci != 0) { const ClazzFieldInfo* fi = ci->findField(ci, name, flags); if (fi != 0 && fi->accessor != 0) { DmiClient& dc = AcdkDmiClient::getDmiClient(); ScriptVar sv; fi->accessor(dynamic_cast<acdk::lang::Object*>(this), name, sv, dc, MiReadOnly | MiAiOut, ci, fi); return SysField::getField(fi, sv); } } { SysFields sysfields = getInternalFields(flags); SysFields::iterator it = sysfields.begin(); SysFields::iterator end = sysfields.end(); for (; it != end; ++it) { if ((*it).fieldInfo->getMetaInfo()->equalsName(name) == true) return *it; } // ### THROW return SysField(); } } /* //static const ClazzFieldInfo* StdDispatch::lookupMember( const ClazzInfo*& clazz, IN(RString) membername, int flags) { if (clazz == 0) { acdk::lang::Object* o = dynamic_cast<acdk::lang::Object*>(this); clazz = o->getClazzInfo(); } clazz = clazz->loadFullClazzInfo(); for (int i = 0; i < clazz->getFieldsCount(); ++i) { if (membername.equals(clazz->fields[i]->name) == true && Modifier::checkMemberAccess(flags, clazz->fields[i]->flags) return clazz->fields[i]; } if ((MiIvDeclared & flags) == 0) { if (flags & MiIvTransientCall) flags |= MiProtected; const ClazzInfo* tclazz = clazz; for (int i = 0; i < tclazz->getInterfacesCount(); i++) { clazz = tclazz->interfaces[i]->type; const ClazzFieldInfo* cfi = lookupMember(clazz, *fname, flags, vec); if (cfi != 0) return cfi; } } StringBuffer sb("Field not found: "); sb.append(Modifier::toString(Modifier::accessMask(flags) | Modifier::staticMask(flags))); sb.append(" "); clazz->toTypeString(sb, false); sb.append("::"); sb.append(&membername); THROW1(NoSuchMethodException, sb.toString()); return SysField(); } //static const ClazzFieldInfo* StdDispatch::lookupStaticMember( const ClazzInfo*& clazz, IN(RString) membername, int flags) { int i; if (clazz->fields != 0) { for (i = 0; clazz->fields[i] != 0; i++) { const ClazzFieldInfo* cfi = clazz->fields[i]; if (membername.equals(cfi->name) == true) { if (cfi->address != 0 && cfi->address != (void*)-1) // otherwise doesn't work with DClazzInfo { if (Modifier::checkMemberAccess(flags, cfi->flags) == true) { return cfi; } } } } } const ClazzInfo* tclazz = clazz; if (tclazz->interfaces != 0 && (MiIvDeclared & flags) == 0) { if (flags & MiIvTransientCall) flags |= MiProtected; const ClazzFieldInfo* cfi; for (i = 0; tclazz->interfaces[i]; i++) { clazz = tclazz->interfaces[i]->type; cfi = lookupStaticMember(clazz, membername, flags); if (cfi != 0) return cfi; } } clazz = tclazz; return 0; } */ //static ScriptVar StdDispatch::getStaticMember(const ClazzInfo* clazz, const ClazzFieldInfo* field, int flags) { if (field->accessor != 0) { return _getMember(0, clazz, field, field->name, AcdkDmiClient::getDmiClient(), MiStatic); } void* address = field->address; const ClazzInfo* clazzInfo = field->type; if (clazzInfo == ClazzInfo::getBoolClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((bool*)address)); else return outOf(*((bool*)address)); } else return inOf(*((bool*)address)); } if (clazzInfo == ClazzInfo::getCharClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((char*)address)); else return outOf(*((char*)address)); } else return inOf(*((char*)address)); } if (clazzInfo == ClazzInfo::getByteClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((byte*)address)); else return outOf(*((byte*)address)); } else return inOf(*((byte*)address)); } if (clazzInfo == ClazzInfo::getShortClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((short*)address)); else return outOf(*((short*)address)); } else return inOf(*((short*)address)); } if (clazzInfo == ClazzInfo::getIntClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((int*)address)); else return outOf(*((int*)address)); } else return inOf(*((int*)address)); } if (clazzInfo == ClazzInfo::getLongClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((jlong*)address)); else return outOf(*((jlong*)address)); } else return inOf(*((jlong*)address)); } if (clazzInfo == ClazzInfo::getFloatClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((float*)address)); else return outOf(*((float*)address)); } else return inOf(*((float*)address)); } if (clazzInfo == ClazzInfo::getDoubleClazz()) { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((double*)address)); else return outOf(*((double*)address)); } else return inOf(*((double*)address)); } // otherwise { if (flags & MiAiOut) { if (flags & MiAiIn) return inoutOf(*((acdk::lang::Object*)address)); else return outOf(*((acdk::lang::Object*)address)); } else return inOf(*((acdk::lang::Object*)address)); } } //static void StdDispatch::setStaticMember(const ClazzInfo* clazz, IN(RString) fieldname, const ScriptVar& newval, DmiClient& dc, int flags) { clazz = clazz->loadFullClazzInfo(); if (clazz->flags & MiCiWeakBind) { ScriptVar ret; ScriptVarArray args(2); args[0] = &fieldname; args[1] = newval; clazz->static_dispatch("poke_static", ret, args, dc, Nil, flags, clazz, 0); return; } const ClazzFieldInfo* fi = ClazzInfo::findField(clazz, fieldname, flags | MiStatic); ScriptVar sv = newval; dc.castTo(sv, fi->type); _setMember(0, sv, clazz, fi, fieldname, dc, flags); } //static void StdDispatch::setStaticMember(const ClazzInfo* clazz, const ClazzFieldInfo* field, const ScriptVar& value, DmiClient& dc, int flags) { if (flags & MiCiWeakBind) { setStaticMember(clazz, ACDK_STACK_STR(field->name), value, dc, flags); return; } // ### todo check flags for protecttion if (field->accessor != 0) { _setMember(0, value, clazz, field, field->name, AcdkDmiClient::getDmiClient(), MiStatic); return; } const ClazzInfo* clazzInfo = field->type; void* address = field->address; if (clazzInfo == ClazzInfo::getBoolClazz()) { *((bool*)address) = value.getBoolVar(); return; } if (clazzInfo == ClazzInfo::getCharClazz()) { *((char*)address) = value.getCharVar(); return; } if (clazzInfo == ClazzInfo::getByteClazz()) { *((byte*)address) = value.getByteVar(); return; } if (clazzInfo == ClazzInfo::getShortClazz()) { *((short*)address) = value.getShortVar(); return; } if (clazzInfo == ClazzInfo::getIntClazz()) { *((int*)address) = value.getIntVar(); return; } if (clazzInfo == ClazzInfo::getLongClazz()) { *((jlong*)address) = value.getLongVar(); return; } if (clazzInfo == ClazzInfo::getFloatClazz()) { *((float*)address) = value.getFloatVar(); return; } if (clazzInfo == ClazzInfo::getDoubleClazz()) { *((double*)address) = value.getDoubleVar(); return; } *((acdk::lang::Object*)address) = value.getObjectVar(); } //static void StdDispatch::poke_static(IN(RString) clsname, IN(RString) member, IN(ScriptVar) val, int flags) { RClass cls = Class::forName(clsname); if (cls == Nil) THROW1(ClassNotFoundException, "Class cannot be found: " + clsname->getName()); StdDispatch::setStaticMember(cls->objectClazzInfo(), member, val, AcdkDmiClient::getDmiClient(), flags); } //static ScriptVar StdDispatch::peek_static(IN(RString) clsname, IN(RString) member, int flags) { RClass cls = Class::forName(clsname); if (cls == Nil) THROW1(ClassNotFoundException, "Class cannot be found: " + clsname->getName()); return StdDispatch::getStaticMember(cls->objectClazzInfo(), member, AcdkDmiClient::getDmiClient(), flags) ; } ScriptVar StdDispatch::New(IN(RString) classname, ScriptVarArray& args, DmiClient& dc) { return New(classname, args, Nil, dc); } ScriptVar StdDispatch::New(IN(RString) classname, ScriptVarArray& args, IN(RStringArray) nargs, DmiClient& dc) { RString constructorname = classname->replace('.', '/'); if (constructorname->indexOf('/') != -1) constructorname = constructorname->substr(constructorname->lastIndexOf('/') + 1); ScriptVar ret; StandardDispatch(classname, constructorname , ret , args , dc , nargs , MiPublic | MiIvConstructor //| MiStatic , 0); return ret; } //static ScriptVar StdDispatch::New(IN(RString) classname, ScriptVarArray& args, IN(NamedArgs) nargs, DmiClient& dc) { StringArray namedArgs(nargs.size()); args.reserve(args.size() + nargs.size()); for (int i = 0; i < nargs.size(); ++i) { namedArgs[i] = new String(nargs[i]._name); args.push_back(*nargs[i]._val); } RString constructorname = classname->replace('.', '/'); if (constructorname->indexOf('/') != -1) constructorname = constructorname->substr(constructorname->lastIndexOf('/') + 1); ScriptVar ret; StandardDispatch(classname, constructorname , ret , args , dc , &namedArgs , MiPublic | MiMiConstructor //| MiStatic , 0); return ret; } //foreign static ScriptVar StdDispatch::invokeStaticMethod(IN(RString) classname, IN(RString) funcname , ScriptVarArray& args, int flags) { ScriptVar ret; StandardDispatch(classname, funcname, ret, args, ::acdk::lang::dmi::AcdkDmiClient::getDmiClient(), Nil, flags, 0); return ret; } //foreign static ScriptVar StdDispatch::invokeStaticMethod( IN(RString) classname, IN(RString) funcname , ScriptVarArray& args , IN(NamedArgs) nargs , int flags ) { StringArray namedArgs(nargs.size()); args.reserve(args.size() + nargs.size()); for (int i = 0; i < nargs.size(); ++i) { namedArgs[i] = new String(nargs[i]._name); args.push_back(*nargs[i]._val); } return invokeStaticMethod(classname, funcname, args, ::acdk::lang::dmi::AcdkDmiClient::getDmiClient(), &namedArgs, flags); } //foreign static ScriptVar StdDispatch::invokeStaticMethod( IN(RString) classname, IN(RString) funcname , ScriptVarArray& args , DmiClient& dc , IN(::acdk::lang::RStringArray) namedArgs// = Nil , int flags ) { ScriptVar ret; StandardDispatch(classname, funcname, ret, args, dc, namedArgs, flags, 0, 0); return ret; } //foreign ScriptVar StdDispatch::invokeMethod(IN(RString) funcname, ScriptVarArray& args, int flags) { ScriptVar erg; standardDispatch(funcname, erg, args, getDmiClient(), Nil, flags, getClazzInfo(), 0); return erg; } //foreign ScriptVar StdDispatch::invokeMethod(IN(RString) funcname, ScriptVarArray& args, IN(NamedArgs) nargs, int flags) { StringArray namedArgs(nargs.size()); args.reserve(args.size() + nargs.size()); for (int i = 0; i < nargs.size(); ++i) { namedArgs[i] = new String(nargs[i]._name); args.push_back(*nargs[i]._val); } return invokeMethod(funcname, args, &namedArgs, flags); } //foreign ScriptVar StdDispatch::invokeMethod(IN(RString) funcname, ScriptVarArray& args , DmiClient& dc , IN(::acdk::lang::RStringArray) namedArgs , int flags ) { ScriptVar erg; standardDispatch(funcname, erg, args, dc, namedArgs, flags, getClazzInfo(), 0); return erg; } //foreign ScriptVar StdDispatch::invokeMethod( IN(RString) funcname, ScriptVarArray& args , IN(::acdk::lang::RStringArray) namedArgs, int flags) { ScriptVar erg; standardDispatch(funcname, erg, args, getDmiClient(), namedArgs, flags, getClazzInfo(), 0); return erg; } //foreign ScriptVar StdDispatch::peek(IN(RString) fieldname, int flags) { return getMember(fieldname, getDmiClient(), flags, 0); } //foreign void StdDispatch::poke(IN(RString) fieldname, const ScriptVar& arg, int flags) { setMember(fieldname, arg, getDmiClient(), flags); } inline ::acdk::lang::RString isOperator(IN(RString) fname) { RString strOperator = ACDK_STACK_STR("operator"); if (fname->startsWith(strOperator) == true) { if (acdk::lang::Character::isJavaIdentifierPart(fname->charAt(strOperator->length())) == false) return fname->substr(strOperator->length()); } return Nil; } class FunctionDescriptor { public: int getParamCount() const { return 0; } const ClazzInfo* getParamType(int i) const { return 0; } int getParamFlags(int i) const { return 0; } bool equalsParamName(int i, IN(RString) pname) const { return false; } bool hasDefaultValue(int i) const { return false; } ScriptVar getDefaultValue(int i) const { return ScriptVar(); } }; class ClazzMethodInfoDescriptor : public FunctionDescriptor { public: const ClazzMethodInfo* _mi; ClazzMethodInfoDescriptor(const ClazzMethodInfo* mi) : _mi(mi) {} int getParamCount() const { return _mi->getArgumentCount(); } const ClazzInfo* getParamType(int i) const { return _mi->methodArgs[i]->type; } int getParamFlags(int i) const { return _mi->methodArgs[i]->flags; } bool equalsParamName(int i, IN(RString) pname) const { return _mi->methodArgs[i]->equalsName(pname); } bool hasDefaultValue(int i) const { return _mi->methodArgs[i]->getDefaultArgValueFunc != 0; } ScriptVar getDefaultValue(int i) const { return _mi->methodArgs[i]->getDefaultArgValueFunc(_mi->methodArgs[i]); } }; class NamedArgDescription { protected: RStringArray namedargs; public: NamedArgDescription(IN(RStringArray) n) : namedargs(n) {} bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; } int getNamedCount() const { return namedargs == Nil ? 0 : namedargs->length(); } RString getNameArgName(int argCount, int idx) { /* a, b, c: C, d: D idx = 2 (c) argCount = 4; namedArg = 2 realidx = 0 idx = (c) argCount = 4; namedArg = 2 realidx = 0 */ int realIdx = idx - (argCount - namedargs->length()); return namedargs[realIdx]; } }; class ScriptVarArgDescription : public NamedArgDescription { ScriptVarArray& args; public: typedef ScriptVar ElementType; typedef ScriptVarArray ElementContainer; ScriptVarArgDescription(ScriptVarArray& a, IN(RStringArray) nargs) : NamedArgDescription(nargs), args(a) {} int getCount() const { return args.size(); } bool hasValues() const { return true; } ScriptVar& getValue(int idx) { return args[idx]; } const ClazzInfo* getType(int idx) const { return args[idx].getValueClazzInfo(); } int getUnnamedCount() const { if (hasNamed() == false) return getCount(); return getCount() - namedargs->length(); } RString getName(int idx) { return getNameArgName(getCount(), idx); } const ElementContainer& elementContainer() const { return args; } const ElementType& get(int idx) const { return args[idx]; } void set(int idx, const ElementType& et) { args[idx] = et; } void resetElement(int idx) { args[idx].reset(); } void resize(int newSize) { args.resize(newSize); } void setValue(int idx, const ScriptVar& sv) { args[idx] = sv; } }; class MethodArgInfoArgDesc : public NamedArgDescription { ::acdk::lang::sys::core_vector<ClazzMethodArgInfo>& args; public: typedef ClazzMethodArgInfo ElementType; typedef ::acdk::lang::sys::core_vector<ClazzMethodArgInfo> ElementContainer; MethodArgInfoArgDesc(::acdk::lang::sys::core_vector<ClazzMethodArgInfo>& a, IN(RStringArray) nargs) : NamedArgDescription(nargs) , args(a) {} int getCount() const { return args.size(); } bool hasValues() const { return false; } ScriptVar& getValue(int idx) { static ScriptVar voidSv; return voidSv; } const ClazzInfo* getType(int idx) const { return args[idx].type; } bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; } int getUnnamedCount() const { if (hasNamed() == false) return getCount(); return getCount() - namedargs->length(); } int getNamedCount() const { return namedargs == Nil ? 0 : namedargs->length(); } RString getName(int idx) { return getNameArgName(getCount(), idx); } const ElementContainer& elementContainer() const { return args; } const ElementType& get(int idx) const { return args[idx]; } void set(int idx, const ElementType& et) { args[idx] = et; } void resetElement(int idx) { } void resize(int newSize) { args.resize(newSize); } // not supported, hasValues() == false void setValue(int idx, const ScriptVar& sv) { } }; class MethodArgInfoPtrArgDesc : public NamedArgDescription { ClazzMethodArgInfo** args; int count; public: typedef ClazzMethodArgInfo ElementType; typedef ClazzMethodArgInfo** ElementContainer; MethodArgInfoPtrArgDesc(acdk::lang::dmi::ClazzMethodArgInfo** a, IN(RStringArray) nargs) : NamedArgDescription(nargs) , args(a) , count(0) { if (args != 0) { for (int i = 0; args[i] != 0; ++i) ++count; } } int getCount() const { return count; } bool hasValues() const { return false; } ScriptVar& getValue(int idx) { static ScriptVar voidSv; return voidSv; } const ClazzInfo* getType(int idx) const { return args[idx]->type; } bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; } int getUnnamedCount() const { if (hasNamed() == false) return getCount(); return getCount() - namedargs->length(); } int getNamedCount() const { return namedargs == Nil ? 0 : namedargs->length(); } RString getName(int idx) { return getNameArgName(getCount(), idx); } const ElementContainer& elementContainer() const { return args; } const ElementType& get(int idx) const { return *args[idx]; } void set(int idx, const ElementType& et) { } void resetElement(int idx) { } void resize(int newSize) { } // not supported, hasValues() == false void setValue(int idx, const ScriptVar& sv) { } }; class FunctionSignatureArgDesc : public NamedArgDescription { FunctionSignature& args; public: typedef const ClazzInfo* ElementType; typedef const ClazzInfo** ElementContainer; FunctionSignatureArgDesc(FunctionSignature& a, IN(RStringArray) nargs) : NamedArgDescription(nargs) , args(a) { } int getCount() const { return args.size; } bool hasValues() const { return false; } ScriptVar& getValue(int idx) { static ScriptVar voidSv; return voidSv; } const ClazzInfo* getType(int idx) const { return args.args[idx]; } bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; } int getUnnamedCount() const { if (hasNamed() == false) return getCount(); return getCount() - namedargs->length(); } int getNamedCount() const { return namedargs == Nil ? 0 : namedargs->length(); } RString getName(int idx) { return getNameArgName(getCount(), idx); } ElementContainer& elementContainer() { return args.args; } ElementType& get(int idx) { return args.args[idx]; } void set(int idx, const ElementType& et) { } void resetElement(int idx) { } void resize(int newSize) { } // not supported, hasValues() == false void setValue(int idx, const ScriptVar& sv) { } }; template <class CMD, class ARGS> bool hasRestParam(const CMD& mi, ARGS& args) { bool hasRest = (mi.getParamCount() > 0) && ClazzInfo::isRestArg(mi.getParamType(mi.getParamCount() - 1)); if (hasRest == false) return false; int argCount = args.getCount(); if (argCount == 0) return true; int paramCount = mi.getParamCount(); if (args.getType(argCount - 1) == DmiObjectArray::clazzInfo() && argCount == paramCount) return false; return true; } template <class CMD, class ARGS> bool hasNamedRestParam(const CMD& mi, ARGS& args) { bool hasRest = (mi.getParamCount() > 0) && ClazzInfo::isNamedRestArg(mi.getParamType(mi.getParamCount() - 1)); if (hasRest == false) return false; int argCount = args.getCount(); if (argCount == 0) return true; if (args.getType(argCount - 1) == DmiNamedArgArray::clazzInfo()) return false; return true; } //static void StdDispatch::findFunctions(const ClazzInfo* clazz, IN(RString) funcname, int flags, ClazzMethodInfoVec& vec) { if (clazz == 0) return; clazz = clazz->loadFullClazzInfo(); int i; RString opmethod; RString opChar; RString fname = funcname; if ((opChar = isOperator(funcname)) != Nil) { opmethod = acdk::lang::reflect::Method::encodeOperatorToFuncName(opChar); fname = opmethod; } if (clazz->methods != 0) { for (i = 0; clazz->methods[i]; i++) { const ClazzMethodInfo* cmi = clazz->methods[i]; if (MetaInfo::checkMemberAccess(flags, cmi->flags) == false) continue; // ## TODO check MiIvViaAltName flag if (cmi->equalsName(fname) == false && cmi->equalsAltName(fname) == false) continue; vec.push_back(cmi); } } if (clazz->interfaces != 0 && (MiIvDeclared & flags) == 0 && (MiMiConstructor & flags) == 0) { if (flags & MiIvTransientCall) flags |= MiProtected; for (i = 0; clazz->interfaces[i]; i++) { findFunctions(clazz->interfaces[i]->type, fname, flags, vec); } } } void asSignature(StringBuffer& sb, ScriptVarArray& args) { for (int i = 0; i < args.size(); ++i) { if (i > 0) sb.append(", "); sb.append(args[i].getTypeInfo()); } } /* bool MethodInfo_hasRestParam(const ClazzMethodInfo* mi) { return (mi->getArgumentCount() > 0 && ClazzInfo::isRestArg(mi->methodArgs[mi->getArgumentCount() - 1]->type)); } bool MethodInfo_hasNamedRestParam(const ClazzMethodInfo* mi) { return (mi->getArgumentCount() > 0 && ClazzInfo::isNamedRestArg(mi->methodArgs[mi->getArgumentCount() - 1]->type)); }*/ //static const ClazzMethodInfo* StdDispatch::_lookupMethod(const ClazzInfo*& clazz, IN(RString) fname, ScriptVarArray& args, DmiClient& dc, int flags, const ClazzMethodInfo* methinf) { return _lookupMethod(clazz, fname, args, Nil, dc, flags, methinf); /* dead method const ClazzInfo* tclazz = clazz; if (flags & MiIvViaHash) { int methhash = ACDK_CAST_PTR2INT(methinf); const ClazzMethodInfo* cmi = lookupMethod(clazz, methhash, flags); if (cmi == 0 && (flags & MiIvNoThrowIfNotFound) == 0) ClazzMethodInfo::throwMethodNotFound(tclazz, Integer::toString(methhash), flags, dc._formatFlags); return cmi; } if (fname->length() == 0 || clazz == 0) { if ((flags & MiIvNoThrowIfNotFound) == 0) THROW1(NoSuchDmiElementException, "Class or method not not defined"); return 0; } // ## TODO check MiIvViaAltName RString rfname = fname; if ((flags & MiIvConstructor) == MiIvConstructor && clazz->isArray() == true) { const ClazzInfo* eltype = clazz->userInfo; //clazz->getArrayElementType(); if (rfname->startsWith(eltype->name) == true) { if (eltype->isBasicClazz() == true) rfname = "ObjectArrayBaseImpl"; // ###typo?? else rfname = "ObjectArrayBaseImpl"; } else if (*eltype->name == '[') { rfname = "ObjectArrayBaseImpl"; } } ClazzMethodInfoVec methods; findFunctions(clazz, rfname, flags, methods); if (methods.size() == 0) { if ((flags & MiIvNoThrowIfNotFound) == 0) ClazzMethodInfo::throwMethodNotFound(tclazz, &fname, flags, dc._formatFlags); return 0; } int lastmatch = 0; //ClazzMethodInfoVec lastBestMatch; const ClazzMethodInfo* lastBestMatch = 0; ClazzMethodInfoVec::iterator it = methods.begin(); ClazzMethodInfoVec::iterator end = methods.end(); for (; it != end; ++it) { const ClazzMethodInfo* cmi = *it; int mcount = cmi->getArgumentCount(); bool hasRestParam = MethodInfo_hasRestParam(cmi); bool hasNamedRestParam = MethodInfo_hasNamedRestParam(cmi); if (mcount != args.size()) { if (hasRestParam == false && hasNamedRestParam == false) continue; } bool canasign = true; int total = 0; bool wasViaNamedRest = false; for (int j = 0; j < mcount; j++) { if (j == mcount - 1 && (hasRestParam == true || hasNamedRestParam == true)) { wasViaNamedRest = true; break; } int match; if (cmi->methodArgs[j]->flags & MiAiOut) match = dc.typeDistance(cmi->methodArgs[j]->type, args[j].getClazzInfo()); else match = dc.typeDistance(args[j], cmi->methodArgs[j]->type); if (match == -1) { canasign = false; break; } total += match; } if (canasign == true) { if (total == 0) { if (wasViaNamedRest == false) { clazz = reinterpret_cast<const ClazzInfo*>(cmi->_scopeParent); return cmi; } else total = 1024; } if ((total < lastmatch) || (lastBestMatch == 0)) { lastmatch = total; lastBestMatch = *it; } } } if (lastBestMatch != 0) { clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent); return lastBestMatch; } StringBuffer sb(1024); sb.append("No matching function found: "); clazz->toTypeString(sb, dc._formatFlags); if (dc._formatFlags & TpFtAcdkType) sb.append("::"); else sb.append("."); sb.append(fname); sb.append("("); asSignature(sb, args); sb.append(")\n Following functions are defined:\n"); for (int i = 0; i < methods.size(); ++i) { sb.append("\t"); const ClazzInfo* parent = (const ClazzInfo*)methods[i]->_scopeParent; if (clazz->isArray() == true) parent = clazz; methods[i]->toTypeString(sb, reinterpret_cast<const ClazzInfo*>(parent), dc._formatFlags); sb.append("\n"); } if ((flags & MiIvNoThrowIfNotFound) == 0) THROW3(ParamsMismatchException, sb.toString(), clazz, methods); return 0; */ } int matchParameter(const ClazzInfo* paramType, int paramFlag, ScriptVar& sv, DmiClient& dc) { if (paramFlag & MiAiOut) return dc.typeDistance(paramType, sv.getClazzInfo()); else return dc.typeDistance(sv, paramType); } int matchParameter(const ClazzInfo* paramType, int paramFlag, const ClazzInfo* argType, DmiClient& dc) { if (paramFlag & MiAiOut) return dc.typeDistance(paramType, argType); else return dc.typeDistance(argType, paramType); } template <class CMD, class ARGS> int matchParameters(const ClazzInfo* clazz, const CMD& cmi, ARGS& args, int argCount , DmiClient& dc, int flags) { int matchSum = 0; for (int i = 0; i < argCount; ++i) { int match = -1; if (args.hasValues() == true) match = matchParameter(cmi.getParamType(i), cmi.getParamFlags(i), args.getValue(i), dc); else match = matchParameter(cmi.getParamType(i), cmi.getParamFlags(i), args.getType(i), dc); if (match == -1) return -1; matchSum += match; } return matchSum; } /** return weight of this matching method does not check if method has */ template <class CMD, class ARGS> int matchSimpleMethod(const ClazzInfo* clazz, const CMD& cmi, ARGS& args , DmiClient& dc , int flags , OUT(RbyteArray) order ) { bool hasRest = hasRestParam(cmi, args); bool hasNamedRest = hasNamedRestParam(cmi, args); int argCount = args.getCount(); int paramCount = cmi.getParamCount(); if (hasNamedRest == true) { --paramCount; } if (argCount != paramCount && hasRest == false) return -1; if (hasRest == false) return matchParameters(clazz, cmi, args, argCount, dc, flags); int c = matchParameters(clazz, cmi, args, paramCount - 1, dc, flags); if (c == -1) return -1; c += (argCount - (paramCount - 1)) * 1024; order = new byteArray(argCount); int i; for (i = 0; i < paramCount - 1; ++i) order[i] = i; for (i = paramCount - 1; i < argCount; ++i) order[i] = -1; return c; } template <class CMD, class ARGS> int matchNamedArgsMethod(const ClazzInfo* clazz, const CMD& cmi, ARGS& args , DmiClient& dc , int flags, OUT(RbyteArray) order) { bool hasNamedRest = hasNamedRestParam(cmi, args); int argCount = args.getCount(); int paramCount = cmi.getParamCount(); int namedArgCount = args.getNamedCount(); int unnamedArgCount = args.getUnnamedCount(); int mc = matchParameters(clazz, cmi, args, unnamedArgCount, dc, flags); if (mc == -1) return -1; if (argCount != paramCount && hasNamedRest == false) return -1; order = new byteArray(argCount, 0xfe); int i; for (i = 0; i < unnamedArgCount; ++i) order[i] = i; for (i = unnamedArgCount; i < argCount; ++i) { int namedIdx = i - unnamedArgCount; bool foundNamed = false; RString narg = args.getName(i); for (int j = unnamedArgCount; j < paramCount; ++j) { if (cmi.equalsParamName(j, narg) == true) { int m = -1; if (args.hasValues() == true) m = matchParameter(cmi.getParamType(j), cmi.getParamFlags(j), args.getValue(i), dc); else m = matchParameter(cmi.getParamType(j), cmi.getParamFlags(j), args.getType(i), dc); if (m == -1) return -1; order[i] = j; mc += m; foundNamed = true; break; } } if (foundNamed == false) { if (hasNamedRest == false) return -1; break; } } /** try to match default parameter doesn't work currently for (i = 0; i < paramCount; ++i) { int fidx = order->findFirst(byte(i)); if (fidx == -1) { if (cmi.hasDefaultValue(i) == false) return -1; } } */ mc += (argCount - (i - 1)) * 1024; for (; i < argCount; ++i) order[i] = -1; return mc; } template <class CMD, class ARGS> int matchMethod(const ClazzInfo* clazz, const CMD& cmi, ARGS& args , DmiClient& dc , int flags , OUT(RbyteArray) order) { if (args.hasNamed() == false) { return matchSimpleMethod(clazz, cmi, args, dc, flags, order); } return matchNamedArgsMethod(clazz, cmi, args, dc, flags, order); } template <class CMD, class ARGS> void mapArguments(const ClazzInfo*& clazz, const CMD& cmd, ARGS& args, IN(RbyteArray) lastnewargpos) { bool hasNamedRest = hasNamedRestParam(cmd, args); bool hasRest = hasRestParam(cmd, args); bool restAdded = false; int argsCount = args.getCount(); if (lastnewargpos != Nil) { typename ARGS::ElementContainer argssic = args.elementContainer(); int i; for (i = 0; i < argsCount; ++i) { int newpos = lastnewargpos[i]; if (newpos == 0xff) break; else if (newpos == 0xfe) { /*### not working if (lastBestMatch->methodArgs[i]->getDefaultArgValueFunc != 0) args[i] = lastBestMatch->methodArgs[i]->getDefaultArgValueFunc(lastBestMatch->methodArgs[i]); else ; //Ooops */ } else if (newpos != i) { args.resetElement(newpos); args.set(newpos, argssic[i]); } } if (i != argsCount) { int fixed = i; int calcUnmappedsize = 0; for (int ti = lastnewargpos->length() - 1; ti >= 0; --ti) { if (lastnewargpos[ti] != 0xff) break; ++calcUnmappedsize; } if (args.hasValues() == true) { if (hasNamedRest = true && args.hasNamed() == true) { int unmapped = argsCount - fixed; RDmiNamedArgArray rest = new DmiNamedArgArray(unmapped); int mc = 0; for (int naidx = 0; i < argsCount; ++i, ++naidx) { RString narg = args.getName(i); rest[naidx] = new DmiNamedArg(narg, new DmiObject(args.getValue(i))); } args.resize(fixed + 1); args.setValue(fixed, inOf(rest)); restAdded = true; } else if (hasRest == true) { int unmapped = argsCount - fixed; RDmiObjectArray rest = new DmiObjectArray(unmapped); for (; i < argsCount; ++i) { rest[i - fixed] = new DmiObject(args.getValue(i)); } args.resize(fixed + 1); args.setValue(fixed, inOf(rest)); restAdded = true; } } } } if (hasNamedRest == true && restAdded == false) { RDmiNamedArgArray rest = new DmiNamedArgArray(0); args.resize(argsCount + 1); args.setValue(argsCount, inOf(rest)); } if (hasRest == true && restAdded == false) { RDmiObjectArray rest = new DmiObjectArray(0); args.resize(argsCount + 1); args.setValue(argsCount, inOf(rest)); } } /* standard lookup used by dmi */ //static const ClazzMethodInfo* StdDispatch::_lookupMethod( const ClazzInfo*& clazz , IN(RString) fname , ScriptVarArray& args , IN(RStringArray) namedargs , DmiClient& dc , int flags , const ClazzMethodInfo* methinf ) { const ClazzInfo* tclazz = clazz; if (flags & MiIvViaHash) { int methhash = ACDK_CAST_PTR2INT(methinf); const ClazzMethodInfo* cmi = lookupMethod(clazz, methhash, flags); if (cmi == 0 && (flags & MiIvNoThrowIfNotFound) == 0) ClazzMethodInfo::throwMethodNotFound(tclazz, Integer::toString(methhash), flags, dc._formatFlags); return cmi; } if (fname->length() == 0 || clazz == 0) { if ((flags & MiIvNoThrowIfNotFound) == 0) THROW1(NoSuchDmiElementException, "Class or method not defined"); return 0; } RString rfname = fname; if ((flags & MiIvConstructor) == MiIvConstructor && clazz->isArray() == true) { const ClazzInfo* eltype = clazz->userInfo; //clazz->getArrayElementType(); if (rfname->startsWith(eltype->name) == true) { if (eltype->isBasicClazz() == true) rfname = "ObjectArrayBaseImpl"; // ###typo?? else rfname = "ObjectArrayBaseImpl"; } else if (*eltype->name == '[') { rfname = "ObjectArrayBaseImpl"; } } ClazzMethodInfoVec methods; findFunctions(clazz, rfname, flags, methods); if (methods.size() == 0) { if ((flags & MiIvNoThrowIfNotFound) == MiIvNoThrowIfNotFound) return 0; StringBuffer sb; sb.append("Method not found: "); MetaInfo::flagsToTypeDecl(sb, flags, dc._formatFlags); sb.append(" "); tclazz->toTypeString(sb, dc._formatFlags); sb.append("::"); sb.append(fname); sb.append("(...)"); THROW1(NoSuchMethodException, sb.toString()); } int lastmatch = 0; const ClazzMethodInfo* lastBestMatch = 0; /* idx is original position newargpos[i] is new position if position is -1 the argument belongs to Named or unnamed rest */ RbyteArray newargpos; RbyteArray lastnewargpos = Nil; ClazzMethodInfoVec::iterator it = methods.begin(); ClazzMethodInfoVec::iterator end = methods.end(); for (; it != end; ++it) { const ClazzMethodInfo* cmi = *it; ClazzMethodInfoDescriptor cmd(cmi); ScriptVarArgDescription argdesc(args, namedargs); int m = matchMethod(clazz, cmd, argdesc, dc,flags, newargpos); if (m == -1) continue; if (m == 0 || lastmatch == 0 || lastmatch > m) { lastBestMatch = cmi; lastmatch = m; lastnewargpos = newargpos; if (m == 0) break; } } if (lastBestMatch == 0) { if ((flags & MiIvNoThrowIfNotFound) == MiIvNoThrowIfNotFound) return 0; StringBuffer sb(1024); sb.append("No matching function found: "); tclazz->toTypeString(sb, dc._formatFlags); sb.append("::"); sb.append(fname); sb.append("("); asSignature(sb, args); sb.append(")\n Following functions are defined:\n"); for (int i = 0; i < methods.size(); ++i) { sb.append("\t"); const ClazzInfo* parent = (const ClazzInfo*)methods[i]->_scopeParent; if (tclazz->isArray() == true) parent = tclazz; methods[i]->toTypeString(sb, reinterpret_cast<const ClazzInfo*>(parent), dc._formatFlags); sb.append("\n"); } THROW3(ParamsMismatchException, sb.toString(), tclazz, methods); } ClazzMethodInfoDescriptor cmd(lastBestMatch); ScriptVarArgDescription argdesc(args, namedargs); mapArguments(clazz, cmd, argdesc, lastnewargpos); /* bool hasNamedRest = hasNamedRestParam(cmd); bool hasRest = hasRestParam(cmd); bool restAdded = false; if (lastmatch == 0 && hasNamedRest == false && hasRest == false) return lastBestMatch; if (lastnewargpos != Nil) { ScriptVarArray argssic = args; int i; for (i = 0; i < args.size(); ++i) { int newpos = lastnewargpos[i]; int argsCount = args.size(); if (newpos == 0xff) break; else if (newpos == 0xfe) { if (lastBestMatch->methodArgs[i]->getDefaultArgValueFunc != 0) args[i] = lastBestMatch->methodArgs[i]->getDefaultArgValueFunc(lastBestMatch->methodArgs[i]); else ; //Ooops } else if (newpos != i) { args[newpos].reset(); args[newpos] = argssic[i]; } } if (i != args.size()) { int fixed = i; int calcUnmappedsize = 0; for (int ti = lastnewargpos->length() - 1; ti >= 0; --ti) { if (lastnewargpos[ti] != 0xff) break; ++calcUnmappedsize; } ClazzMethodInfoDescriptor cmd(lastBestMatch); if (hasNamedRestParam(cmd) == true) { int unmapped = args.size() - fixed; RDmiNamedArgArray rest = new DmiNamedArgArray(unmapped); int mc = 0; int unMappedOffset = namedargs->length() - calcUnmappedsize; for (int naidx = 0; i < args.size(); ++i, ++naidx) { RString narg = namedargs[unMappedOffset + naidx]; rest[naidx] = new DmiNamedArg(narg, new DmiObject(args[i])); } args.resize(fixed + 1); args[fixed] = &rest; restAdded = true; } else if (hasRestParam(cmd) == true) { int unmapped = args.size() - fixed; RDmiObjectArray rest = new DmiObjectArray(unmapped); for (; i < args.size(); ++i) { rest[i - fixed] = new DmiObject(args[i]); } args.resize(fixed + 1); args[fixed] = &rest; restAdded = true; } } } if (hasNamedRest == true && restAdded == false) { RDmiNamedArgArray rest = new DmiNamedArgArray(0); args.resize(args.size() + 1); args[args.size() - 1] = &rest; } if (hasRest == true && restAdded == false) { RDmiObjectArray rest = new DmiObjectArray(0); args.resize(args.size() + 1); args[args.size() - 1] = &rest; } */ clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent); return lastBestMatch; /* int mcount = 0; int nargsc = namedargs->length(); int unamedargsc = 0; newargpos = new byteArray(args.size(), (byte)-1); const ClazzMethodInfo* cmi = *it; mcount = cmi->getArgumentCount(); bool hasNamedRest = MethodInfo_hasNamedRestParam(cmi); if (hasNamedRest == true) mcount -= 1; else if (mcount != args.size()) continue; if (hasNamedRest == true) unamedargsc = mcount; else unamedargsc = mcount - nargsc; bool canasign = true; int total = 0; for (int j = 0; j < unamedargsc; j++) { int match; if (cmi->methodArgs[j]->flags & MiAiOut) match = dc.typeDistance(cmi->methodArgs[j]->type, args[j].getClazzInfo()); else match = dc.typeDistance(args[j], cmi->methodArgs[j]->type); if (match == -1) { canasign = false; break; } total += match; } if (canasign == true) { for (int j = unamedargsc; j < mcount; j++) // checke named values { bool foundp = false; int mapped = 0; //for (mapped = 0; mapped < nargsc && mapped + j < mcount; ++mapped) // seek positinal for (mapped = 0; mapped < nargsc && mapped + unamedargsc < mcount; ++mapped) // seek positinal { RString narg = namedargs[mapped]; if (cmi->methodArgs[j]->equalsName(narg) == true) { int match = dc.typeDistance(args[unamedargsc + mapped], cmi->methodArgs[j]->type); if (match == -1) { canasign = false; break; } newargpos[unamedargsc + mapped] = j; foundp = true; total += match; break; } } if (foundp == false) { canasign = false; break; } } if (total == 0 && canasign == true) { lastBestMatch = *it; lastnewargpos = newargpos; goto foundMethod; } if (canasign == true && (total < lastmatch) || (lastBestMatch == 0)) { lastmatch = total; lastnewargpos = newargpos; lastBestMatch = *it; } } } foundMethod: // reorder ScriptVar elements in order of the named values if (lastBestMatch != 0) { bool hasNamedRest = MethodInfo_hasNamedRestParam(lastBestMatch); if (hasNamedRest == true) { int mcount = lastBestMatch->getArgumentCount(); int fixed = mcount - 1; int unmapped = args.size() - fixed; RDmiNamedArgArray rest = new DmiNamedArgArray(unmapped); int mc = 0; for (int i = 0; i < unmapped; ++i) { RString narg = namedargs[i]; rest[i] = new DmiNamedArg(narg, new DmiObject(args[fixed + i])); } args.resize(fixed + 1); args[fixed] = &rest; clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent); return lastBestMatch; } bool reorder = false; int i; int mcount = lastBestMatch->getArgumentCount(); int nargsc = namedargs->length(); int unamedargsc = mcount - nargsc; for (i = unamedargsc; i < args.size(); ++i) { if (lastnewargpos[i] != i) { reorder = true; } } if (reorder == false) { clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent); return lastBestMatch; } ScriptVarArray argssic = args; for (i = unamedargsc; i < args.size(); ++i) { if (lastnewargpos[i] != i && char(lastnewargpos[i]) != -1) { args[lastnewargpos[i]].reset(); args[lastnewargpos[i]] = argssic[i]; } } clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent); return lastBestMatch; } if ((flags & MiIvNoThrowIfNotFound) == MiIvNoThrowIfNotFound) return 0; StringBuffer sb(1024); sb.append("No matching function found: "); clazz->toTypeString(sb, dc._formatFlags); sb.append("::"); sb.append(fname); sb.append("("); asSignature(sb, args); sb.append(")\n Following functions are defined:\n"); for (int i = 0; i < methods.size(); ++i) { sb.append("\t"); const ClazzInfo* parent = (const ClazzInfo*)methods[i]->_scopeParent; if (clazz->isArray() == true) parent = clazz; methods[i]->toTypeString(sb, reinterpret_cast<const ClazzInfo*>(parent), dc._formatFlags); sb.append("\n"); } THROW3(ParamsMismatchException, sb.toString(), clazz, methods); return 0; */ } void asSignature(::acdk::lang::StringBuffer& sb, ::acdk::lang::sys::core_vector<ClazzMethodArgInfo>& args) { for (int i = 0; i < args.size(); ++i) { if (i > 0) sb.append(", "); args[i].toTypeString(sb, TpFtFormatStandard); } } /* used by Class::getMethod() */ //static const ClazzMethodInfo* StdDispatch::_lookupMethod( const ClazzInfo*& clazz , IN(RString) fname , ::acdk::lang::sys::core_vector<ClazzMethodArgInfo>& args , IN(RStringArray) namedargs , DmiClient& dc , int flags ) { if (fname->length() == 0 || clazz == 0) { if (MiIvNoThrowIfNotFound & flags) return 0; THROW1(NoSuchDmiElementException, "DMI: class not defined"); } ClazzMethodInfoVec methods; findFunctions(clazz, fname, flags, methods); if (methods.size() == 0) { if (MiIvNoThrowIfNotFound & flags) return 0; StringBuffer sb; sb.append("Method not found: "); MetaInfo::flagsToTypeDecl(sb, flags, dc._formatFlags); //sb.append(Modifier::toString(Modifier::accessMask(flags) | Modifier::staticMask(flags))); sb.append(" "); clazz->toTypeString(sb, dc._formatFlags); sb.append("::"); sb.append(fname); sb.append("(...)"); THROW1(NoSuchMethodException, sb.toString()); } int lastmatch = 0; const ClazzMethodInfo* lastBestMatch = 0; int nargsc = namedargs == Nil ? 0 : namedargs->length(); int unamedargsc = 0; ClazzMethodInfoVec::iterator it = methods.begin(); ClazzMethodInfoVec::iterator end = methods.end(); int mcount = 0; RbyteArray newargpos; RbyteArray lastnewargpos = Nil; for (; it != end; ++it) { const ClazzMethodInfo* cmi = *it; ClazzMethodInfoDescriptor cmd(cmi); MethodArgInfoArgDesc argdesc(args, namedargs); int m = matchMethod(clazz, cmd, argdesc, dc, flags, newargpos); if (m == -1) continue; if (m == 0 || lastmatch == 0 || lastmatch > m) { lastBestMatch = cmi; lastmatch = m; lastnewargpos = newargpos; if (m == 0) break; } /* newargpos = new byteArray(args.size()); const ClazzMethodInfo* cmi = *it; mcount = cmi->getArgumentCount(); if (mcount != args.size()) continue; unamedargsc = mcount - nargsc; bool canasign = true; int total = 0; for (int j = 0; j < mcount - nargsc; j++) { int match; if (cmi->methodArgs[j]->flags & MiAiOut) match = dc.typeDistance(cmi->methodArgs[j]->type, args[j].type); else match = dc.typeDistance(args[j].type, cmi->methodArgs[j]->type); if (match == -1) { canasign = false; break; } total += match; } if (canasign == true) { for (int j = unamedargsc; j < mcount; j++) // checke named values { bool foundp = false; for (int i = 0; i < nargsc; ++i) // seek positinal { RString narg = namedargs[i]; if (cmi->methodArgs[j]->equalsName(narg) == true) { int match = dc.typeDistance(args[unamedargsc + i].type, cmi->methodArgs[j]->type); if (match == -1) { canasign = false; break; } newargpos[unamedargsc + i] = j; foundp = true; total += match; } } if (foundp == false) { canasign = false; break; } } if (total == 0 && canasign == true) { lastBestMatch = *it; lastnewargpos = newargpos; goto foundMethod; } if ((total < lastmatch) || (lastBestMatch == 0)) { lastmatch = total; lastnewargpos = newargpos; lastBestMatch = *it; } } */ } foundMethod: // reorder ScriptVar elements in order of the named values if (lastBestMatch != 0) { ClazzMethodInfoDescriptor cmd(lastBestMatch); MethodArgInfoArgDesc argdesc(args, namedargs); mapArguments(clazz, cmd, argdesc, lastnewargpos); /* bool reorder = false; int i; for (i = unamedargsc; i < args.size(); ++i) { if (lastnewargpos[i] != i) { reorder = true; } } if (reorder == false) { clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent); return lastBestMatch; } ::acdk::lang::sys::core_vector<ClazzMethodArgInfo> argssic = args; for (i = unamedargsc; i < args.size(); ++i) { if (lastnewargpos[i] != i) { args[lastnewargpos[i]] = argssic[i]; } } */ clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent); return lastBestMatch; } StringBuffer sb(1024); sb.append("No matching function found: "); clazz->toTypeString(sb, dc._formatFlags); sb.append("::"); sb.append(fname); sb.append("("); asSignature(sb, args); sb.append(")\n Following functions are defined:\n"); for (int i = 0; i < methods.size(); ++i) { sb.append("\t"); const ClazzInfo* parent = (const ClazzInfo*)methods[i]->_scopeParent; if (clazz->isArray() == true) parent = clazz; methods[i]->toTypeString(sb, reinterpret_cast<const ClazzInfo*>(parent), dc._formatFlags); sb.append("\n"); } THROW3(ParamsMismatchException, sb.toString(), clazz, methods); return 0; } //static const ClazzMethodInfo* StdDispatch::lookupMethod( const ClazzInfo*& clazz , IN(RString) fname , ScriptVarArray& args , IN(RStringArray) namedArgs , DmiClient& dc , int flags , const ClazzMethodInfo* methinf ) { return _lookupMethod(clazz, fname, args, namedArgs, dc, flags, methinf); /* if (namedArgs == Nil) { const ClazzMethodInfo* cmi = _lookupMethod(clazz, fname, args, namedArgs, dc, flags, methinf); if (cmi == 0) // if _lookupMethod didn't thrown an ex, MiIvNoThrowIfNotFound is set return 0; int mcount = cmi->getArgumentCount(); bool hasRest = MethodInfo_hasRestParam(cmi); bool hasNamedRest = MethodInfo_hasNamedRestParam(cmi); if (hasRest == true || hasNamedRest == true) mcount -= 1; for (int j = 0; j < mcount; j++) { dc.castTo(args[j], cmi->methodArgs[j]->type); } if (hasRest == true) { RDmiObjectArray rest = new DmiObjectArray(args.size() - mcount); int baseidx = 0; for (int i = mcount; i < args.size(); ++i, ++baseidx) { rest[baseidx] = new DmiObject(args[i]); } args.resize(mcount + 1); args[mcount] = &rest; } else if (hasNamedRest == true) { RDmiNamedArgArray rest = new DmiNamedArgArray(0); args.resize(args.size() + 1); args[args.size() - 1] = &rest; } return cmi; } else return _lookupMethod(clazz, fname, args, namedArgs, dc, flags, methinf); */ } //static const ClazzMethodInfo* StdDispatch::lookupMethod( const ClazzInfo*& clazz , IN(::acdk::lang::RString) fname , acdk::lang::dmi::ClazzMethodArgInfo** const args , DmiClient& dc , int flags ) { ClazzMethodInfoVec methods; StdDispatch::findFunctions(clazz, fname, flags, methods); if (methods.size() == 0) return 0; ClazzMethodInfoVec::iterator it = methods.begin(); ClazzMethodInfoVec::iterator end = methods.end(); const ClazzMethodInfo* cmi = *it; const ClazzMethodInfo* lastBestMatch = 0; RbyteArray newargpos; RbyteArray lastnewargpos; int mcount = 0; int acount = 0; int lastmatch = 0; for (; args != 0 && args[acount] != 0; ++acount) ; bool canasign = true; int total = 0; for (; it != end; ++it) { const ClazzMethodInfo* cmi = *it; ClazzMethodInfoDescriptor cmd(cmi); MethodArgInfoPtrArgDesc argsDesc(args, Nil); int m = matchMethod(clazz, cmd, argsDesc, dc,flags, newargpos); if (m == -1) continue; if (m == 0 || lastmatch == 0 || lastmatch > m) { lastBestMatch = cmi; lastmatch = m; lastnewargpos = newargpos; if (m == 0) break; } /* mcount = cmi->getArgumentCount(); if (mcount != acount) continue; for (int j = 0; j < acount; j++) { int match; if (cmi->methodArgs[j]->flags & MiAiOut) match = dc.typeDistance(cmi->methodArgs[j]->type, args[j]->type); else match = dc.typeDistance(args[j]->type, cmi->methodArgs[j]->type); if (match == -1) { canasign = false; break; } total += match; } if (total == 0 && canasign == true) { lastBestMatch = *it; goto foundMethod; } if ((total < lastmatch) || (lastBestMatch == 0)) { lastmatch = total; lastBestMatch = *it; } */ } foundMethod: if (lastBestMatch != 0) return lastBestMatch; return lastBestMatch; } //static const ClazzMethodInfo* StdDispatch::lookupMethod( const ClazzInfo*& clazz, IN(RString) fname, int flags) { if (clazz == 0) return 0; clazz = clazz->loadFullClazzInfo(); int i; if (clazz->methods != 0) { for (i = 0; clazz->methods[i]; i++) { const ClazzMethodInfo* cmi = clazz->methods[i]; if (MetaInfo::checkMemberAccess(flags, clazz->methods[i]->flags) == false) continue; if (cmi->equalsName(fname) == true) return cmi; } } const ClazzMethodInfo* cmi; if (clazz->interfaces != 0 && (MiIvDeclared & flags) == 0) { const ClazzInfo* tclazz = clazz; if (flags & MiIvTransientCall) flags |= MiProtected; for (i = 0; tclazz->interfaces[i] != 0; i++) { clazz = tclazz->interfaces[i]->type; cmi = lookupMethod(clazz, fname, flags); if (cmi != 0) return cmi; } clazz = tclazz; } return 0; } //static const ClazzMethodInfo* StdDispatch::lookupMethod( const ClazzInfo*& clazz, int methodhash, int flags) { int i; clazz = clazz->loadFullClazzInfo(); for (i = 0; i < clazz->getMethodsCount(); ++i) { if (clazz->methods[i]->getMethodSignatureHashValue() == methodhash) { if (MetaInfo::checkMemberAccess(flags, clazz->methods[i]->flags) == false) return 0; return clazz->methods[i]; } } if (MiIvDeclared & flags) return 0; const ClazzInfo* tclazz = clazz; for (i = 0; tclazz->interfaces[i] != 0; i++) { if (flags & MiIvTransientCall) flags |= MiProtected; clazz = tclazz->interfaces[i]->type; const ClazzMethodInfo* merg = lookupMethod(clazz, methodhash, flags); if (merg != 0) return merg; clazz = tclazz; } return 0; } bool StdDispatch::isDmiOverLoaded(const ClazzInfo* ci, const ClazzMethodInfo* mi) { if ((DmiClient::getCurInvokeFlags() & MiIvNoWeakBind) != 0) return false; return isDmiOverLoaded(ci, mi->name, mi, mi->methodArgs); } // virtual bool StdDispatch::isDmiOverLoaded(const ClazzInfo* ci, IN(RString) funcname, const ClazzMethodInfo* mi, ClazzMethodArgInfo**const args) { if (mi != 0) { } // #### maybe implement me return false; } RString getClassMethodDevider(int formatFlags) { if (formatFlags & TpFtJavaType) return "."; if (formatFlags & TpFtLoadableClass || formatFlags & TpFtJavaSignature) return "/"; return "::"; } void throwNonPolyMethodNotFound(const ClazzInfo* clazz, IN(RString) fname, int formatFlags) { StringBuffer sb; clazz->toTypeString(sb, formatFlags); sb.append(getClassMethodDevider(formatFlags)); sb.append(fname); THROW1(NoSuchMethodException, "No such Method: " + sb.toString()); } const ClazzMethodInfo* StdDispatch::lookupMethodNoPolymorph( const ClazzInfo*& clazz , IN(RString) fname , ScriptVarArray& args , IN(RStringArray) namedArgs , DmiClient& dc , int flags , const ClazzMethodInfo* methinf ) { clazz = clazz->loadFullClazzInfo(); int i; for (i = 0; i < clazz->getMethodsCount(); ++i) { const ClazzMethodInfo* cmi = clazz->methods[i]; if (cmi->altlabel != 0) { if (cmi->equalsAltName(fname) == true) return cmi; } if (cmi->equalsName(fname) == true) return cmi; } if (flags & MiIvDeclared) { if (flags & MiIvNoThrowIfNotFound) return 0; throwNonPolyMethodNotFound(clazz, fname, dc._formatFlags); } const ClazzInfo* tclazz = clazz; for (i = 0; clazz->interfaces[i]; i++) { clazz = tclazz->interfaces[i]->type; const ClazzMethodInfo* ret = lookupMethodNoPolymorph(clazz, fname, args, Nil, dc, flags | MiIvNoThrowIfNotFound); if (ret != 0) return ret; clazz = tclazz; } if ((flags & MiIvNoThrowIfNotFound) == 0) throwNonPolyMethodNotFound(tclazz, fname, dc._formatFlags); return 0; } const ClazzMethodInfo* StdDispatch::findMethod(const ClazzInfo*& ci, const FunctionSignature& signature, bool exactMatch, int flags) { int i; if (ci == 0) return 0; ci = ci->loadFullClazzInfo(); for (i = 0; i < ci->getMethodsCount(); i++) { //### maybe used with FunctionSignatureArgDesc if (strcmp(ci->methods[i]->name, signature.functionname) == 0) { int mcount = ci->methods[i]->getArgumentCount(); if (mcount == signature.size) { bool canasign = true; for (int j = 0; j < mcount; j++) { if (ci->methods[i]->methodArgs[j] == 0) { canasign = false; break; } if (exactMatch == true) { if (signature.args[j] != ci->methods[i]->methodArgs[j]->type) { canasign = false; break; } } else { if (AcdkDmiClient::getDmiClient().typeDistance(ci->methods[i]->methodArgs[j]->type, signature.args[j]) == -1) { canasign = false; break; } } } if (canasign == true) { return ci->methods[i]; } } } } const ClazzMethodInfo* merg = 0; if (ci->interfaces != 0 && (MiIvDeclared & flags) == 0) { const ClazzInfo* tclazz = ci; for (i = 0; i < tclazz->getInterfacesCount(); i++) { if (flags & MiIvTransientCall) flags |= MiProtected; ci = tclazz->interfaces[i]->type; merg = findMethod(ci, signature, exactMatch, flags); if (merg != 0) return merg; ci = tclazz; } } return 0; } /* used by acdkx_orb? not used anymore //static const ClazzMethodInfo* StdDispatch::findMethod(const ClazzInfo*& ci, IN(RString) funcname, ArgumentExprTypes& types, int flags, bool exactMatch) { int i; if (ci == 0) return 0; ci = ci->loadFullClazzInfo(); int lastDistance = -1; int lastmethodidx = -1; int curDistance = 0; if (ci->methods == 0) goto searchInSuper; for (i = 0; ci->methods[i]; i++) { if (funcname == Nil || ci->methods[i]->equalsName(funcname) == true || ci->methods[i]->equalsAltName(funcname) == true ) { int mcount = 0; if (ci->methods[i]->methodArgs != 0) { while (ci->methods[i]->methodArgs[mcount++]) ; --mcount; } if (mcount > 0 && (MethodInfo_hasRestParam(ci->methods[i]) == true || MethodInfo_hasNamedRestParam(ci->methods[i]) == true)) { ; } else if (mcount != types.size()) goto searchNextMethod; curDistance = 0; bool canasign = true; int lastPositionalArg = 0; for (int j = 0; j < mcount; j++) { if (types[j]._argName != 0) { if (ClazzInfo::isNamedRestArg(ci->methods[i]->methodArgs[j]->type) == true) break; types[j]._position = -1; for (int k = lastPositionalArg; k < mcount; ++k) { if (strcmp(types[j]._argName, ci->methods[i]->methodArgs[k]->name) == 0) { types[j]._position = k; break; } } if (types[j]._position == -1) // positional arg not found goto searchNextMethod; if (exactMatch == true) { if (types[j]._type != ci->methods[i]->methodArgs[types[j]._position]->type) goto searchNextMethod; } else { if (AcdkDmiClient::getDmiClient().typeDistance(types[j]._type, ci->methods[i]->methodArgs[types[j]._position]->type ) == -1) goto searchNextMethod; } } else // not a named arg { if (ci->methods[i]->methodArgs[j] == 0) { canasign = false; break; } if (ClazzInfo::isRestArg(ci->methods[i]->methodArgs[j]->type) == true) break; if (exactMatch == true) { if (types[j]._type != ci->methods[i]->methodArgs[j]->type) goto searchNextMethod; types[j]._position = j; } else { int dist = AcdkDmiClient::getDmiClient().typeDistance(types[j]._type, ci->methods[i]->methodArgs[j]->type); if (dist == -1) goto searchNextMethod; types[j]._position = j; lastPositionalArg = j; curDistance += dist; } } } if (curDistance < lastDistance || lastDistance == -1) { lastDistance = curDistance; lastmethodidx = i; } } searchNextMethod: continue; } if (lastmethodidx != -1) return ci->methods[lastmethodidx]; searchInSuper: const ClazzMethodInfo* merg = 0; if (ci->interfaces != 0 && (MiIvDeclared & flags) == 0) { for (i = 0; ci->interfaces[i]; i++) { if (flags & MiIvTransientCall) flags |= MiProtected; ci = ci->interfaces[i]->type; merg = findMethod(ci, funcname, types, flags, exactMatch); if (merg != 0) return merg; } } return 0; } */ } // dmi } // lang } // acdk |