Example #1
0
DaoValue* DaoObject_CastToBase( DaoObject *self, DaoType *host )
{
	DaoValue *sup = self->parent;
	if( host == NULL ) return NULL;
	host = DaoType_GetBaseType( host );
	if( self->defClass->objType == host ) return (DaoValue*) self;
	if( self->parent == NULL ) return NULL;
	if( sup->type == DAO_OBJECT ){
		if( (sup = DaoObject_CastToBase( & sup->xObject, host ) ) ) return sup;
	}else if( sup->type == DAO_CSTRUCT && host->tid == DAO_CSTRUCT ){
		if( DaoType_ChildOf( sup->xCdata.ctype, host ) ) return sup;
	}else if( sup->type == DAO_CDATA && host->tid == DAO_CDATA ){
		if( DaoType_ChildOf( sup->xCdata.ctype, host ) ) return sup;
	}
	return NULL;
}
Example #2
0
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;
}
Example #3
0
/*
// Assumming the value "self" is compatible to the type "tp", if it is not null.
*/
DaoValue* DaoValue_SimpleCopyWithTypeX( DaoValue *self, DaoType *tp, DaoType *cst )
{
	if( self == NULL ) return dao_none_value;
	if( self->type < DAO_ENUM && (tp == NULL || tp->tid == self->type) ){
		/*
		// The following optimization is safe theoretically.
		// But it is not practically safe for DaoProcess_PutChars() etc.,
		// which often uses shallow wraps of "const char*" as the source value,
		// and expects it to be copied at the destination as a primitive value.
		*/
		/* if( cst && cst->invar ) return self; */
		switch( self->type ){
		case DAO_NONE : return self;
		case DAO_BOOLEAN : return (DaoValue*) DaoBoolean_New( self->xBoolean.value );
		case DAO_INTEGER : return (DaoValue*) DaoInteger_New( self->xInteger.value );
		case DAO_FLOAT   : return (DaoValue*) DaoFloat_New( self->xFloat.value );
		case DAO_COMPLEX : return (DaoValue*) DaoComplex_New( self->xComplex.value );
		case DAO_STRING  : return (DaoValue*) DaoString_Copy( & self->xString );
		}
		return self; /* unreachable; */
	}else if( tp && tp->tid >= DAO_BOOLEAN && tp->tid <= DAO_FLOAT ){
		DaoValue *va = NULL;
		switch( tp->tid ){
		case DAO_BOOLEAN : va = (DaoValue*) DaoBoolean_New( DaoValue_GetInteger(self) ); break;
		case DAO_INTEGER : va = (DaoValue*) DaoInteger_New( DaoValue_GetInteger(self) ); break;
		case DAO_FLOAT   : va = (DaoValue*) DaoFloat_New( DaoValue_GetFloat(self) );   break;
		}
		return va;
	}else if( self->type == DAO_ENUM ){
		switch( tp ? tp->tid : 0 ){
		case DAO_ENUM :
			if( tp->subtid == DAO_ENUM_ANY ) tp = NULL;
			return (DaoValue*) DaoEnum_Copy( & self->xEnum, tp );
		case DAO_BOOLEAN : return (DaoValue*) DaoBoolean_New( self->xEnum.value );
		case DAO_INTEGER : return (DaoValue*) DaoInteger_New( self->xEnum.value );
		case DAO_FLOAT   : return (DaoValue*) DaoFloat_New( self->xEnum.value );
		}
		return (DaoValue*) DaoEnum_Copy( & self->xEnum, NULL );
	}else if( tp && tp->tid == DAO_ENUM ){
		switch( self->type ){
		case DAO_BOOLEAN :
		case DAO_INTEGER : return (DaoValue*) DaoEnum_New( tp, self->xInteger.value );
		case DAO_FLOAT   : return (DaoValue*) DaoEnum_New( tp, self->xFloat.value );
		}
	}else if( self->type == DAO_CINVALUE ){
		return (DaoValue*) DaoCinValue_Copy( (DaoCinValue*) self );
	}
	if( tp != NULL ){
		assert( tp->tid == 0 || tp->tid > DAO_ENUM );
		assert( self->type == 0 || self->type > DAO_ENUM );
	}

#ifdef DAO_WITH_NUMARRAY
	if( self->type == DAO_ARRAY && self->xArray.original ){
		DaoArray_Sliced( (DaoArray*)self );
		return self;
	}else
#endif
	if( self->type == DAO_CSTRUCT || self->type == DAO_CDATA ){
		if( self->xCstruct.ctype->core->Slice ) self->xCstruct.ctype->core->Slice( self );
		return self;
	}
	if( tp == NULL ){
		switch( self->type ){
		case DAO_LIST  : if( self->xList.ctype->empty ) tp = self->xList.ctype; break;
		case DAO_MAP   : if( self->xMap.ctype->empty  ) tp = self->xMap.ctype; break;
		default : break;
		}
	}
	if( self->xBase.trait & DAO_VALUE_NOCOPY ) return self;
	if( (self->xBase.trait & DAO_VALUE_CONST) == 0 ) return self;
	if( cst != NULL && cst->invar != 0 ) return self;
	if( tp ) tp = DaoType_GetBaseType( tp );
	return DaoValue_CopyContainer( self, tp );
}