int DaoType_MatchInterface( DaoType *self, DaoInterface *inter, DMap *binds ) { DMap *inters = self->interfaces; DNode *it; if( inter == NULL ) return DAO_MT_NOT; if( inters == NULL ){ return DAO_MT_SUB * (DaoInterface_BindTo( inter, self, binds ) == NULL); } if( (it = DMap_Find( inters, inter )) ){ return it->value.pRoutine ? DAO_MT_NOT : DAO_MT_SUB; } return DAO_MT_SUB * (DaoInterface_BindTo( inter, self, binds ) == NULL); }
int DaoType_MatchInterface( DaoType *self, DaoInterface *inter, DMap *binds ) { DMap *inters = self->interfaces; DNode *it; daoint i; if( inter == NULL ) return DAO_MT_NOT; if( inter->abtype->kernel->SetupMethods ){ DaoTypeKernel *kernel = inter->abtype->kernel; kernel->SetupMethods( kernel->nspace, kernel->typer ); } if( inters == NULL ) return DAO_MT_SUB * DaoInterface_BindTo( inter, self, binds ); if( (it = DMap_Find( inters, inter )) ) return it->value.pVoid ? DAO_MT_SUB : DAO_MT_NOT; return DAO_MT_SUB * DaoInterface_BindTo( inter, self, binds ); }
DaoValue* DaoValue_Convert( DaoValue *self, DaoType *type, int copy, DaoProcess *proc ) { DaoTypeCore *core = DaoValue_GetTypeCore( self ); DaoValue *value = self; DaoType *at; if( type->tid & DAO_ANY ){ if( copy == 0 ) return value; at = DaoValue_GetType( value, proc->vmSpace ); at = DaoType_GetBaseType( at ); if( at == NULL ) return NULL; if( DaoType_IsImmutable( at ) ) return value; if( value->type >= DAO_ARRAY && value->type <= DAO_TUPLE ){ at = DaoNamespace_MakeInvarSliceType( proc->activeNamespace, at ); return DaoValue_CopyContainer( value, at ); }else if( core != NULL && core->Copy != NULL ){ return core->Copy( value, NULL ); } return NULL; }else if( type->tid == DAO_CINVALUE ){ DaoCinType *cintype = (DaoCinType*) type->aux; if( value->type == DAO_CINVALUE && value->xCinValue.cintype == cintype ) return value; if( value->type == DAO_CINVALUE && DaoType_MatchValue( type, value, NULL ) ) return value; at = DaoNamespace_GetType( proc->activeNamespace, value ); if( cintype->target == at || DaoType_MatchTo( cintype->target, at, NULL ) >= DAO_MT_CIV ){ proc->cinvalue.cintype = cintype; proc->cinvalue.value = value; return (DaoValue*) & proc->cinvalue; } return NULL; }else if( type->tid == DAO_INTERFACE ){ DaoInterface *inter = (DaoInterface*) type->aux; DaoRoutine *incompatible; if( type->aux == NULL ){ /* type "interface": */ if( value->type != DAO_INTERFACE ) return NULL; return value; } if( value->type == DAO_CINVALUE && DaoType_MatchValue( type, value, NULL ) ) return value; at = DaoNamespace_GetType( proc->activeNamespace, value ); if( inter->concretes ){ DaoCinType *cintype = DaoInterface_GetConcrete( inter, at ); if( cintype ){ proc->cinvalue.cintype = cintype; proc->cinvalue.value = value; return (DaoValue*) & proc->cinvalue; } } switch( value->type ){ case DAO_OBJECT : value = (DaoValue*) value->xObject.rootObject; at = value->xObject.defClass->objType; break; case DAO_CSTRUCT : case DAO_CDATA : if( value->xCstruct.object ){ value = (DaoValue*) value->xCstruct.object->rootObject; at = value->xObject.defClass->objType; } break; } /* Automatic binding when casted to an interface: */ incompatible = DaoInterface_BindTo( inter, at, NULL ); if( incompatible != NULL ){ DString *buffer = DString_New(); DString_AppendChars( buffer, "Interface method " ); DString_Append( buffer, inter->abtype->name ); DString_AppendChars( buffer, "::" ); DString_Append( buffer, incompatible->routName ); DString_AppendChars( buffer, "() is not available in the source type;" ); DaoProcess_DeferException( proc, "Error::Type", buffer->chars ); DString_Delete( buffer ); return NULL; } return value; }else if( type->tid == DAO_VARIANT ){ DaoType *best = NULL; int i, n, max = DAO_MT_NOT; for(i=0,n=type->args->size; i<n; i++){ DaoType *itype = type->args->items.pType[i]; int mt = DaoType_MatchValue( itype, self, NULL ); if( mt > max ){ best = itype; max = mt; } } if( best == NULL ) return NULL; return DaoValue_Convert( self, best, copy, proc ); } if( core == NULL || core->DoConversion == NULL ) return NULL; value = core->DoConversion( self, type, copy, proc ); if( value == NULL || value->type <= DAO_ENUM || copy == 0 ) return value; if( value == self /*|| DaoValue_ChildOf( value, self ) || DaoValue_ChildOf( self, value )*/ ){ // No way to determine inheritance relationship between wrapped C++ objects; if( value->type >= DAO_ARRAY && value->type <= DAO_TUPLE ){ DaoType *type = DaoValue_GetType( value, proc->vmSpace ); if( type == NULL ) return NULL; type = DaoNamespace_MakeInvarSliceType( proc->activeNamespace, type ); return DaoValue_CopyContainer( value, type ); } if( core == NULL || core->Copy == NULL ) return NULL; value = core->Copy( value, NULL ); /* Copy invariable value; */ if( value == NULL ) return NULL; DaoProcess_CacheValue( proc, value ); } return value; }