void DaoObject_SetParentCstruct( DaoObject *self, DaoCstruct *parent ) { DaoObject *child = NULL; DaoObject *obj = (DaoObject*) self->parent; DaoValue *sup = self->defClass->parent; if( parent == NULL ) return; if( sup == NULL ) return; if( obj && obj->type == DAO_OBJECT ){ DaoObject_SetParentCstruct( obj, parent ); }else if( sup->type == DAO_CTYPE ){ DaoCtype *ctype = (DaoCtype*)sup; if( DaoType_ChildOf( ctype->classType, parent->ctype ) ){ DaoValue_MoveCstruct( (DaoValue*) parent, & self->parent, 1 ); } } }
void DaoValue_CopyX( DaoValue *src, DaoValue **dest, DaoType *cst ) { DaoValue *dest2 = *dest; if( src == dest2 ) return; if( dest2 && dest2->xBase.refCount >1 ){ GC_DecRC( dest2 ); *dest = dest2 = NULL; } if( src->type == DAO_CSTRUCT || src->type == DAO_CDATA ){ DaoValue_MoveCstruct( src, dest, cst != NULL && cst->invar != 0 ); return; }else if( src->type == DAO_CINVALUE ){ DaoValue_MoveCinValue( (DaoCinValue*) src, dest ); return; } if( dest2 == NULL ){ src = DaoValue_SimpleCopyWithTypeX( src, NULL, cst ); GC_IncRC( src ); *dest = src; return; } if( src->type != dest2->type || src->type > DAO_ENUM ){ src = DaoValue_SimpleCopyWithTypeX( src, NULL, cst ); GC_Assign( dest, src ); return; } switch( src->type ){ case DAO_ENUM : DaoEnum_SetType( & dest2->xEnum, src->xEnum.etype ); DaoEnum_SetValue( & dest2->xEnum, & src->xEnum ); break; case DAO_BOOLEAN : dest2->xBoolean.value = src->xBoolean.value; break; case DAO_INTEGER : dest2->xInteger.value = src->xInteger.value; break; case DAO_FLOAT : dest2->xFloat.value = src->xFloat.value; break; case DAO_COMPLEX : dest2->xComplex.value = src->xComplex.value; break; case DAO_STRING : DString_Assign( dest2->xString.value, src->xString.value ); break; } }
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; }