DaoType* DaoCinValue_CheckConversion( DaoType *self, DaoType *type, DaoRoutine *ctx ) { DaoCinType *cintype = (DaoCinType*) self->aux; DaoTypeCore *core; DaoRoutine *rout; DString *buffer; if( cintype->target == type ){ return type; }else if( DaoType_MatchTo( cintype->target, type, NULL ) >= DAO_MT_EQ ){ return type; } buffer = DString_NewChars( "(" ); DString_Append( buffer, type->name ); DString_AppendChars( buffer, ")" ); rout = DaoType_FindFunction( cintype->vatype, buffer ); DString_Delete( buffer ); if( rout != NULL ){ DaoType *ttype = DaoNamespace_GetType( ctx->nameSpace, (DaoValue*) type ); rout = DaoRoutine_MatchByType( rout, self, & ttype, 1, DVM_CALL ); if( rout ) return type; } core = cintype->target->core; if( core != NULL && core->CheckConversion ){ return core->CheckConversion( cintype->target, type, ctx ); } return NULL; }
DaoValue* DaoCinValue_DoConversion( DaoValue *self, DaoType *type, int copy, DaoProcess *proc ) { DaoCinType *cintype = self->xCinValue.cintype; DaoTypeCore *core; DaoRoutine *rout; DString *buffer; if( cintype->target == type ){ if( copy ) return DaoValue_Convert( self->xCinValue.value, type, copy, proc ); return self->xCinValue.value; }else if( DaoType_MatchTo( cintype->target, type, NULL ) >= DAO_MT_EQ ){ if( copy ) return DaoValue_Convert( self->xCinValue.value, type, copy, proc ); return self->xCinValue.value; } buffer = DString_NewChars( "(" ); DString_Append( buffer, type->name ); DString_AppendChars( buffer, ")" ); rout = DaoType_FindFunction( cintype->vatype, buffer ); DString_Delete( buffer ); if( rout != NULL ){ int rc = DaoProcess_PushCall( proc, rout, self, (DaoValue**) & type, 1 ); if( rc == 0 ) return NULL; } return DaoValue_Convert( self->xCinValue.value, type, copy, proc ); }
static int DaoxDataFrame_SetFrame( DaoxDataFrame *self, DaoxDataFrame *df ) { DaoValue value = {0}; DArray *destSlices = self->slices; DArray *fromSlices = df->slices; DArray *fromSlices2 = df->slices; daoint i, j, k, N, M, K; if( DaoxDataFrame_AlignFrame( self, df ) == 0 ) return DAOX_DF_WRONG_SHAP; if( self->original == NULL ){ DaoxDataFrame_PrepareSlices( self ); DaoxDataFrame_MakeFullSlice( self, self->slices ); destSlices = self->slices; }else{ self = self->original; } if( df->original == NULL ){ fromSlices = DArray_New(D_VECTOR); DaoxDataFrame_MakeFullSlice( df, fromSlices ); }else{ df = df->original; } N = destSlices->items.pVector[0]->data.daoints[1]; M = destSlices->items.pVector[1]->data.daoints[1]; K = destSlices->items.pVector[2]->data.daoints[1]; for(j=0; j<M; ++j){ daoint jjdes = DaoSlice_GetIndex( destSlices->items.pVector[1], j ); daoint jjsrc = DaoSlice_GetIndex( fromSlices->items.pVector[1], j ); DaoxDataColumn *coldes = (DaoxDataColumn*) self->columns->items.pVoid[jjdes]; DaoxDataColumn *colsrc = (DaoxDataColumn*) df->columns->items.pVoid[jjsrc]; if( DaoType_MatchTo( colsrc->type, coldes->type, NULL ) < DAO_MT_SUB ) return DAOX_DF_WRONG_VALUE; for(i=0; i<N; ++i){ daoint iides = DaoSlice_GetIndex( destSlices->items.pVector[0], i ); daoint iisrc = DaoSlice_GetIndex( fromSlices->items.pVector[0], i ); for(k=0; k<K; ++k){ daoint kkdes = DaoSlice_GetIndex( destSlices->items.pVector[2], k ); daoint kksrc = DaoSlice_GetIndex( fromSlices->items.pVector[2], k ); daoint idsrc = kksrc * N + iisrc; daoint iddes = kkdes * N + iides; DaoValue *val = DaoxDataColumn_GetCell( colsrc, idsrc, & value ); DaoxDataColumn_SetCell( coldes, iddes, val ); } } } if( fromSlices != fromSlices2 ) DArray_Delete( fromSlices ); return 0; }
DaoCinType* DaoInterface_GetConcrete( DaoInterface *self, DaoType *type ) { DNode *it; if( self->concretes == NULL ) return NULL; it = DMap_Find( self->concretes, type ); if( it == NULL ){ for(it=DMap_First(self->concretes); it; it=DMap_Next(self->concretes,it)){ if( DaoType_MatchTo( it->key.pType, type, NULL ) >= DAO_MT_EQ ){ return (DaoCinType*) it->value.pVoid; } } return NULL; } return (DaoCinType*) it->value.pVoid; }
static int DaoObject_CheckSetField( DaoType *self, DaoString *name, DaoType *value, DaoRoutine *ctx ) { DaoClass *klass = (DaoClass*) self->aux; DaoType *type = ctx->routHost; DaoClass *host = type != NULL && type->tid == DAO_OBJECT ? (DaoClass*) type->aux : NULL; DaoValue *data = DaoClass_GetData( klass, name->value, host ); DaoRoutine *rout; int error = DAO_OK; error = 0; if( strcmp( name->value->chars, "self" ) ==0 ) return DAO_ERROR_FIELD_HIDDEN; if( data == NULL ){ error = DAO_ERROR_FIELD_ABSENT; }else if( data->type == DAO_NONE ){ error = DAO_ERROR_FIELD_HIDDEN; }else if( data->xBase.subtype == DAO_CLASS_CONSTANT ){ error = DAO_ERROR_FIELD_HIDDEN; // XXX }else{ /* data->xBase.subtype == DAO_CLASS_VARIABLE || DAO_OBJECT_VARIABLE */ if( DaoType_MatchTo( value, data->xVar.dtype, NULL ) == 0 ) return DAO_ERROR_VALUE; } if( error ){ DString *field = DString_NewChars( "." ); DString_Append( field, name->value ); DString_AppendChars( field, "=" ); rout = DaoClass_FindMethod( klass, field->chars, host ); DString_Delete( field ); if( rout != NULL ){ rout = DaoRoutine_MatchByType( rout, self, & value, 1, DVM_CALL ); }else{ DaoType *args[2]; args[0] = dao_type_string; args[1] = value; rout = DaoClass_FindMethod( klass, ".=", host ); if( rout == NULL ) return error; rout = DaoRoutine_MatchByType( rout, self, args, 2, DVM_CALL ); } if( rout == NULL ) return error; } return DAO_OK; }
static void STD_SubType( DaoProcess *proc, DaoValue *p[], int N ) { DaoType *tp1 = DaoNamespace_GetType( proc->activeNamespace, p[0] ); DaoType *tp2 = DaoNamespace_GetType( proc->activeNamespace, p[1] ); DaoProcess_PutInteger( proc, DaoType_MatchTo( tp1, tp2, NULL ) ); }
int DaoValue_Move4( DaoValue *S, DaoValue **D, DaoType *T, DMap *defs, DaoDataCache *cache ) { int tm = 1; switch( (T->tid << 8) | S->type ){ case (DAO_INTEGER << 8) | DAO_INTEGER : case (DAO_INTEGER << 8) | DAO_FLOAT : case (DAO_INTEGER << 8) | DAO_DOUBLE : case (DAO_FLOAT << 8) | DAO_INTEGER : case (DAO_FLOAT << 8) | DAO_FLOAT : case (DAO_FLOAT << 8) | DAO_DOUBLE : case (DAO_DOUBLE << 8) | DAO_INTEGER : case (DAO_DOUBLE << 8) | DAO_FLOAT : case (DAO_DOUBLE << 8) | DAO_DOUBLE : case (DAO_COMPLEX << 8) | DAO_COMPLEX : case (DAO_LONG << 8) | DAO_LONG : case (DAO_STRING << 8) | DAO_STRING : S = DaoValue_SimpleCopyWithTypeX( S, T, cache ); GC_ShiftRC( S, *D ); *D = S; return 1; } if( !(S->xTuple.trait & DAO_VALUE_CONST) ){ DaoType *ST = NULL; switch( (S->type << 8) | T->tid ){ case (DAO_TUPLE<<8)|DAO_TUPLE : ST = S->xTuple.unitype; break; case (DAO_ARRAY<<8)|DAO_ARRAY : ST = dao_array_types[ S->xArray.etype ]; break; case (DAO_LIST <<8)|DAO_LIST : ST = S->xList.unitype; break; case (DAO_MAP <<8)|DAO_MAP : ST = S->xMap.unitype; break; case (DAO_CDATA<<8)|DAO_CDATA : ST = S->xCdata.ctype; break; case (DAO_CSTRUCT<<8)|DAO_CSTRUCT : ST = S->xCstruct.ctype; break; case (DAO_OBJECT<<8)|DAO_OBJECT : ST = S->xObject.defClass->objType; break; } if( ST == T ){ DaoValue *D2 = *D; GC_ShiftRC( S, D2 ); *D = S; return 1; } } if( (T->tid == DAO_OBJECT || T->tid == DAO_CDATA || T->tid == DAO_CSTRUCT) && S->type == DAO_OBJECT ){ if( S->xObject.defClass != & T->aux->xClass ){ S = DaoObject_CastToBase( S->xObject.rootObject, T ); tm = (S != NULL); } }else if( (T->tid == DAO_CLASS || T->tid == DAO_CTYPE) && S->type == DAO_CLASS ){ if( S->xClass.clsType != T && T->aux != NULL ){ /* T->aux == NULL for "class"; */ S = DaoClass_CastToBase( (DaoClass*)S, T ); tm = (S != NULL); } }else if( T->tid == DAO_CTYPE && S->type == DAO_CTYPE ){ if( S->xCtype.ctype != T ){ S = DaoType_CastToParent( S, T ); tm = (S != NULL); } }else if( T->tid == DAO_ROUTINE && T->overloads == 0 && S->type == DAO_ROUTINE && S->xRoutine.overloads ){ DArray *routines = S->xRoutine.overloads->routines; int i, k, n; /* // Do not use DaoRoutine_ResolveByType( S, ... ) // "S" should match to "T", not the other way around! */ tm = 0; for(i=0,n=routines->size; i<n; i++){ DaoRoutine *rout = routines->items.pRoutine[i]; k = rout->routType == T ? DAO_MT_EQ : DaoType_MatchTo( rout->routType, T, defs ); if( k > tm ) tm = k; if( rout->routType == T ){ S = (DaoValue*) rout; break; } } }else{ tm = DaoType_MatchValue( T, S, defs ); } #if 0 if( tm ==0 ){ printf( "T = %p; S = %p, type = %i %i\n", T, S, S->type, DAO_ROUTINE ); printf( "T: %s %i %i\n", T->name->mbs, T->tid, tm ); if( S->type == DAO_LIST ) printf( "%s\n", S->xList.unitype->name->mbs ); if( S->type == DAO_TUPLE ) printf( "%p\n", S->xTuple.unitype ); } printf( "S->type = %p %s %i\n", S, T->name->mbs, tm ); #endif if( tm == 0 ) return 0; /* composite known types must match exactly. example, * where it will not work if composite types are allowed to match loosely. * d : list<list<int>> = {}; * e : list<float> = { 1.0 }; * d.append( e ); * * but if d is of type list<list<any>>, * the matching do not necessary to be exact. */ S = DaoValue_SimpleCopyWithTypeX( S, T, cache ); GC_ShiftRC( S, *D ); *D = S; if( S->type == DAO_TUPLE && S->xTuple.unitype != T && tm >= DAO_MT_SIM ){ return DaoValue_TryCastTuple( S, D, T ); }else if( T && T->tid == S->type && !(T->attrib & DAO_TYPE_SPEC) ){ DaoValue_SetType( S, T ); } return 1; }
DaoClass* DaoClass_Instantiate( DaoClass *self, DArray *types ) { DaoClass *klass = NULL; DaoType *type; DString *name; DNode *node; DMap *deftypes; daoint lt = DString_FindChar( self->className, '<', 0 ); daoint i, holders = 0; if( self->typeHolders == NULL || self->typeHolders->size ==0 ) return self; while( types->size < self->typeHolders->size ){ type = self->typeDefaults->items.pType[ types->size ]; if( type == NULL ) type = self->typeHolders->items.pType[ types->size ]; DArray_Append( types, type ); } name = DString_New(1); DString_Append( name, self->className ); if( lt != MAXSIZE ) DString_Erase( name, lt, MAXSIZE ); DString_AppendChar( name, '<' ); for(i=0; i<types->size; i++){ type = types->items.pType[i]; holders += type->tid == DAO_THT; if( i ) DString_AppendChar( name, ',' ); DString_Append( name, type->name ); } DString_AppendChar( name, '>' ); while( self->templateClass ) self = self->templateClass; node = DMap_Find( self->instanceClasses, name ); if( node ){ klass = node->value.pClass; }else{ deftypes = DMap_New(0,0); klass = DaoClass_New(); if( holders ) klass->templateClass = self; DMap_Insert( self->instanceClasses, name, klass ); DaoClass_AddReference( self, klass ); /* No need for cleanup of klass; */ DaoClass_SetName( klass, name, self->classRoutine->nameSpace ); for(i=0; i<types->size; i++){ type = types->items.pType[i]; if( DaoType_MatchTo( type, self->typeHolders->items.pType[i], deftypes ) ==0 ){ DString_Delete( name ); return NULL; } MAP_Insert( deftypes, self->typeHolders->items.pVoid[i], type ); } klass->objType->nested = DArray_New(D_VALUE); DArray_Assign( klass->objType->nested, types ); if( DaoClass_CopyField( klass, self, deftypes ) == 0 ){ DString_Delete( name ); return NULL; } DaoClass_DeriveClassData( klass ); DaoClass_DeriveObjectData( klass ); DaoClass_ResetAttributes( klass ); DMap_Delete( deftypes ); if( holders ){ klass->typeHolders = DArray_New(0); klass->typeDefaults = DArray_New(0); klass->instanceClasses = DMap_New(D_STRING,0); DMap_Insert( klass->instanceClasses, klass->className, klass ); for(i=0; i<types->size; i++){ DArray_Append( klass->typeHolders, types->items.pType[i] ); DArray_Append( klass->typeDefaults, NULL ); } for(i=0; i<klass->typeHolders->size; i++){ DaoClass_AddReference( klass, klass->typeHolders->items.pType[i] ); DaoClass_AddReference( klass, klass->typeDefaults->items.pType[i] ); } } } DString_Delete( name ); return klass; }
static int DaoType_Compare( DaoType *left, DaoType *right ) { if( DaoType_MatchTo( left, right, NULL ) >= DAO_MT_EQ ) return 0; return number_compare( (size_t)left, (size_t)right ); }
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; }
int DaoValue_Move5( DaoValue *S, DaoValue **D, DaoType *T, DaoType *C, DMap *defs ) { DaoValue *D2 = *D; if( S == D2 && (S == NULL || DaoValue_FastMatchTo( S, T )) ) return 1; if( S == NULL ){ GC_DecRC( *D ); *D = NULL; return 0; } if( T == NULL ){ DaoValue_CopyX( S, D, C ); return 1; } if( T->valtype ){ if( DaoValue_Compare( S, T->value ) !=0 ) return 0; DaoValue_CopyX( S, D, C ); return 1; } switch( T->tid ){ case DAO_UDT : DaoValue_CopyX( S, D, C ); return 1; case DAO_THT : if( T->aux ) return DaoValue_Move5( S, D, (DaoType*) T->aux, C, defs ); DaoValue_CopyX( S, D, C ); return 1; case DAO_ANY : DaoValue_CopyX( S, D, C ); DaoValue_SetType( *D, T ); return 1; case DAO_VARIANT : return DaoValue_MoveVariant( S, D, T, C ); default : break; } if( S->type >= DAO_OBJECT || !(S->xBase.trait & DAO_VALUE_CONST) || T->invar ){ if( DaoValue_FastMatchTo( S, T ) ){ if( S->type == DAO_CDATA && S->xCdata.data == NULL ){ if( ! DaoType_IsNullable( T ) ) return 0; } if( S->type == DAO_CSTRUCT || S->type == DAO_CDATA ){ DaoValue_MoveCstruct( S, D, C != NULL && C->invar != 0 ); }else if( S->type == DAO_CINVALUE ){ DaoValue_MoveCinValue( (DaoCinValue*) S, D ); }else{ GC_Assign( D, S ); } return 1; } } if( S->type == DAO_CINVALUE ){ if( S->xCinValue.cintype->target == T ){ S = S->xCinValue.value; }else if( DaoType_MatchTo( S->xCinValue.cintype->target, T, NULL ) >= DAO_MT_EQ ){ S = S->xCinValue.value; } } if( D2 && D2->xBase.refCount > 1 ){ GC_DecRC( D2 ); *D = D2 = NULL; } #if 0 if( D2 && S->type == D2->type && S->type == T->tid && S->type <= DAO_ENUM ){ switch( S->type ){ case DAO_ENUM : DaoEnum_SetType( & D2->xEnum, T->subtid == DAO_ENUM_ANY ? S->xEnum.etype : T ); return DaoEnum_SetValue( & D2->xEnum, & S->xEnum ); case DAO_BOOLEAN : case DAO_INTEGER : D2->xInteger.value = S->xInteger.value; break; case DAO_FLOAT : D2->xFloat.value = S->xFloat.value; break; case DAO_COMPLEX : D2->xComplex.value = S->xComplex.value; break; case DAO_STRING : DString_Assign( D2->xString.value, S->xString.value ); break; } return 1; } #endif if( D2 == NULL || D2->type != T->tid ) return DaoValue_Move4( S, D, T, C, defs ); switch( (S->type << 8) | T->tid ){ case (DAO_STRING<<8)|DAO_STRING : DString_Assign( D2->xString.value, S->xString.value ); break; case (DAO_ENUM<<8)|DAO_ENUM : DaoEnum_SetType( & D2->xEnum, T->subtid == DAO_ENUM_ANY ? S->xEnum.etype : T ); DaoEnum_SetValue( & D2->xEnum, & S->xEnum ); break; case (DAO_CINVALUE<<8)|DAO_CINVALUE : if( S->xCinValue.cintype->vatype != T ) return DaoValue_Move4( S, D, T, C, defs ); DaoValue_MoveCinValue( (DaoCinValue*) S, D ); break; case (DAO_BOOLEAN<<8)|DAO_BOOLEAN : D2->xBoolean.value = S->xBoolean.value; break; case (DAO_BOOLEAN<<8)|DAO_INTEGER : D2->xInteger.value = S->xBoolean.value; break; case (DAO_BOOLEAN<<8)|DAO_FLOAT : D2->xFloat.value = S->xBoolean.value; break; case (DAO_INTEGER<<8)|DAO_BOOLEAN : D2->xBoolean.value = S->xInteger.value; break; case (DAO_INTEGER<<8)|DAO_INTEGER : D2->xInteger.value = S->xInteger.value; break; case (DAO_INTEGER<<8)|DAO_FLOAT : D2->xFloat.value = S->xInteger.value; break; case (DAO_FLOAT <<8)|DAO_BOOLEAN : D2->xBoolean.value = S->xFloat.value; break; case (DAO_FLOAT <<8)|DAO_INTEGER : D2->xInteger.value = S->xFloat.value; break; case (DAO_FLOAT <<8)|DAO_FLOAT : D2->xFloat.value = S->xFloat.value; break; case (DAO_COMPLEX<<8)|DAO_COMPLEX : D2->xComplex.value = S->xComplex.value; break; default : return DaoValue_Move4( S, D, T, C, defs ); } return 1; }
int DaoValue_Move4( DaoValue *S, DaoValue **D, DaoType *T, DaoType *C, DMap *defs ) { DaoCinType *cintype; int tm = 1; switch( (T->tid << 8) | S->type ){ case (DAO_BOOLEAN << 8) | DAO_BOOLEAN : case (DAO_BOOLEAN << 8) | DAO_INTEGER : case (DAO_BOOLEAN << 8) | DAO_FLOAT : case (DAO_INTEGER << 8) | DAO_BOOLEAN : case (DAO_INTEGER << 8) | DAO_INTEGER : case (DAO_INTEGER << 8) | DAO_FLOAT : case (DAO_FLOAT << 8) | DAO_BOOLEAN : case (DAO_FLOAT << 8) | DAO_INTEGER : case (DAO_FLOAT << 8) | DAO_FLOAT : case (DAO_COMPLEX << 8) | DAO_COMPLEX : case (DAO_STRING << 8) | DAO_STRING : case (DAO_CINVALUE<< 8) | DAO_CINVALUE : S = DaoValue_SimpleCopyWithTypeX( S, T, C ); GC_Assign( D, S ); return 1; } switch( S->type ){ case DAO_ENUM : if( S->xEnum.subtype == DAO_ENUM_SYM && T->realnum ) return 0; break; case DAO_OBJECT : if( S->xObject.isNull ) return 0; break; case DAO_CDATA : if( S->xCdata.data == NULL && ! DaoType_IsNullable(T) ) return 0; break; } if( !(S->xBase.trait & DAO_VALUE_CONST) ){ DaoVmSpace *vms; DaoType *ST = NULL; switch( (S->type << 8) | T->tid ){ case (DAO_ARRAY<<8)|DAO_ARRAY : vms = DaoType_GetVmSpace( T ); ST = vms->typeArrays[ S->xArray.etype ]; break; case (DAO_TUPLE<<8)|DAO_TUPLE : ST = S->xTuple.ctype; break; case (DAO_LIST <<8)|DAO_LIST : ST = S->xList.ctype; break; case (DAO_MAP <<8)|DAO_MAP : ST = S->xMap.ctype; break; case (DAO_CDATA<<8)|DAO_CDATA : ST = S->xCdata.ctype; break; case (DAO_CSTRUCT<<8)|DAO_CSTRUCT : ST = S->xCstruct.ctype; break; case (DAO_OBJECT<<8)|DAO_OBJECT : ST = S->xObject.defClass->objType; break; } if( ST == T ){ if( ST->tid == DAO_CSTRUCT || ST->tid == DAO_CDATA ){ DaoValue_MoveCstruct( S, D, C != NULL && C->invar != 0 ); }else{ GC_Assign( D, S ); } return 1; } } if( (T->tid == DAO_OBJECT || T->tid == DAO_CSTRUCT || T->tid == DAO_CDATA) && S->type == DAO_OBJECT ){ if( S->xObject.defClass != & T->aux->xClass ){ S = DaoObject_CastToBase( S->xObject.rootObject, T ); if( S != NULL && S->type == DAO_CDATA && S->xCdata.data == NULL ){ if( ! DaoType_IsNullable( T ) ) return 0; } tm = (S != NULL); } }else if( (T->tid == DAO_CLASS || T->tid == DAO_CTYPE) && S->type == DAO_CLASS ){ if( S->xClass.clsType != T && T->aux != NULL ){ /* T->aux == NULL for "class"; */ S = DaoClass_CastToBase( (DaoClass*)S, T ); tm = (S != NULL); } }else if( T->tid == DAO_CTYPE && S->type == DAO_CTYPE ){ if( S->xCtype.classType != T ){ S = DaoType_CastToParent( S, T ); tm = (S != NULL); } }else if( T->tid == DAO_ROUTINE && T->subtid != DAO_ROUTINES && S->type == DAO_ROUTINE && S->xRoutine.overloads ){ DList *routines = S->xRoutine.overloads->routines; int i, k, n; /* // Do not use DaoRoutine_ResolveByType( S, ... ) // "S" should match to "T", not the other way around! */ tm = 0; for(i=0,n=routines->size; i<n; i++){ DaoRoutine *rout = routines->items.pRoutine[i]; k = rout->routType == T ? DAO_MT_EQ : DaoType_MatchTo( rout->routType, T, defs ); if( k > tm ) tm = k; if( rout->routType == T ){ S = (DaoValue*) rout; break; } } }else{ tm = DaoType_MatchValue( T, S, defs ); } #if 0 if( tm ==0 ){ printf( "T = %p; S = %p, type = %i %i\n", T, S, S->type, DAO_ROUTINE ); printf( "T: %s %i %i\n", T->name->chars, T->tid, tm ); if( S->type == DAO_LIST ) printf( "%s\n", S->xList.ctype->name->chars ); if( S->type == DAO_TUPLE ) printf( "%p\n", S->xTuple.ctype ); } printf( "S->type = %p %s %i\n", S, T->name->chars, tm ); #endif if( tm == 0 ) return 0; /* // Composite types must match exactly. Example, // where it will not work if composite types are allowed to match loosely. // d : list<list<int>> = {}; // e : list<float> = { 1.0 }; // d.append( e ); // // But if d is of type list<list<any>>, // the matching do not necessary to be exact. */ cintype = NULL; if( T->tid == DAO_CINVALUE ){ if( DaoType_MatchValue( T->aux->xCinType.target, S, NULL ) >= DAO_MT_CIV ){ cintype = (DaoCinType*) T->aux; } }else if( T->tid == DAO_INTERFACE && T->aux->xInterface.concretes ){ DaoInterface *inter = (DaoInterface*) T->aux; DaoType *st = DaoValue_GetType( S, inter->nameSpace->vmSpace ); DNode *it; cintype = DaoInterface_GetConcrete( inter, st ); if( cintype == NULL ){ for(it=DMap_First(inter->concretes); it; it=DMap_Next(inter->concretes,it)){ if( DaoType_MatchValue( it->key.pType, S, NULL ) >= DAO_MT_CIV ){ cintype = (DaoCinType*) it->value.pVoid; break; } } } } if( cintype ){ S = (DaoValue*) DaoCinValue_New( cintype, S ); }else if( S->type == DAO_CSTRUCT || S->type == DAO_CDATA ){ DaoValue_MoveCstruct( S, D, C != NULL && C->invar != 0 ); return 1; }else{ S = DaoValue_SimpleCopyWithTypeX( S, T, C ); } GC_Assign( D, S ); if( S->type == DAO_TUPLE && S->xTuple.ctype != T && tm == DAO_MT_SIM ){ return DaoValue_TryCastTuple( S, D, T ); }else if( T && T->tid == S->type && !(T->attrib & DAO_TYPE_SPEC) ){ DaoValue_SetType( S, T ); } return 1; }