void DaoValue_Update( DaoValue **self, DaoNamespace *ns, DMap *deftypes ) { DaoValue *value = *self; DaoType *tp, *tp2; if( value == NULL || value->type < DAO_ENUM ) return; tp = DaoNamespace_GetType( ns, value ); /* DaoType_DefineTypes() will make proper specialization of template-like type: */ tp2 = DaoType_DefineTypes( tp, ns, deftypes ); if( tp == tp2 ) return; if( tp2->tid == DAO_OBJECT && value->type == DAO_OBJECT && value->xObject.isDefault ){ /* "self" is supposed to be a constant, so it has to be a default instance: */ GC_ShiftRC( tp2->value, value ); /* default instance of specialized Dao class; */ *self = tp2->value; return; }else if( tp2->tid == DAO_CLASS && value->type == DAO_CLASS ){ GC_ShiftRC( tp2->aux, value ); /* specialized Dao class; */ *self = tp2->aux; return; }else if( tp2->tid == DAO_CTYPE && value->type == DAO_CTYPE ){ GC_ShiftRC( tp2->aux, value ); /* specialized C type; */ *self = tp2->aux; return; }else if( tp2->tid == DAO_CDATA && value->type == DAO_CDATA ){ GC_ShiftRC( tp2->value, value ); /* default instance of specialized C type; */ *self = tp2->value; return; }else if( tp2->tid == DAO_CSTRUCT && value->type == DAO_CSTRUCT ){ GC_ShiftRC( tp2->value, value ); /* default instance of specialized C type; */ *self = tp2->value; return; } DaoValue_Move( value, self, tp2 ); }
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; }
/* modules/debugger */ DAO_DLL void Dao_AboutVar( DaoProcess *proc, DaoType *type, DaoValue *var, DString *str ) { DaoType *abtp = DaoNamespace_GetType( proc->activeNamespace, var ); char buf[50]; if( abtp ){ if( var->type == DAO_ROUTINE ){ DString_Append( str, var->xRoutine.routName ); DString_AppendChars( str, "{" ); DString_Append( str, abtp->name ); DString_AppendChars( str, "}" ); }else{ DString_Append( str, abtp->name ); } sprintf( buf, "[%p]", var ); DString_AppendChars( str, buf ); if( var->type == DAO_CDATA ){ sprintf( buf, "(%p)", var->xCdata.data ); DString_AppendChars( str, buf ); } }else{ DString_AppendChars( str, "none[0x0]" ); } if( type ){ DString_AppendChars( str, ":" ); DString_Append( str, type->name ); } }
static int DaoCdata_Serialize( DaoCdata *self, DString *serial, DaoNamespace *ns, DaoProcess *proc, DString *buf, DMap *omap ) { DaoType *type; DaoRoutine *meth = DaoType_FindFunctionMBS( self->ctype, "serialize" ); if( meth == NULL ) return 0; if( DaoProcess_Call( proc, meth, (DaoValue*)self, NULL, 0 ) ) return 0; type = DaoNamespace_GetType( ns, proc->stackValues[0] ); DaoValue_Serialize2( proc->stackValues[0], serial, ns, proc, type, buf, omap ); return 1; }
static int DaoObject_Serialize( DaoObject *self, DString *serial, DaoNamespace *ns, DaoProcess *proc, DString *buf, DMap *omap ) { DaoType *type; DaoValue *value = NULL; DaoValue *selfpar = (DaoValue*) self; DString name = DString_WrapMBS( "serialize" ); int errcode = DaoObject_GetData( self, & name, & value, NULL ); if( errcode || value == NULL || value->type != DAO_ROUTINE ) return 0; if( DaoProcess_Call( proc, (DaoRoutine*)value, selfpar, NULL, 0 ) ) return 0; type = DaoNamespace_GetType( ns, proc->stackValues[0] ); DaoValue_Serialize2( proc->stackValues[0], serial, ns, proc, type, buf, omap ); return 1; }
int DaoValue_Serialize( DaoValue *self, DString *serial, DaoNamespace *ns, DaoProcess *proc ) { DaoType *type = DaoNamespace_GetType( ns, self ); DString *buf = DString_New(1); DMap *omap = DMap_New(0,0); int rc; DString_Clear( serial ); DString_ToMBS( serial ); rc = DaoValue_Serialize2( self, serial, ns, proc, type, buf, omap ); DString_Delete( buf ); DMap_Delete( omap ); return rc; }
static int DaoMap_Serialize( DaoMap *self, DString *serial, DaoNamespace *ns, DaoProcess *proc, DString *buf, DMap *omap ) { DaoType *type = self->unitype; DaoType *keytype = NULL; DaoType *valtype = NULL; DNode *node; char *sep = self->items->hashing ? ":" : "=>"; int i = 0, rc = 1; if( type->nested && type->nested->size >0 ) keytype = type->nested->items.pType[0]; if( type->nested && type->nested->size >1 ) valtype = type->nested->items.pType[1]; if( keytype && (keytype->tid == 0 || keytype->tid >= DAO_ENUM)) keytype = NULL; if( valtype && (valtype->tid == 0 || valtype->tid >= DAO_ENUM)) valtype = NULL; for(node=DMap_First(self->items); node; node=DMap_Next(self->items,node)){ DaoType *kt = NULL, *vt = NULL; if( keytype == NULL ) kt = DaoNamespace_GetType( ns, node->key.pValue ); if( valtype == NULL ) vt = DaoNamespace_GetType( ns, node->value.pValue ); if( (i++) ) DString_AppendChar( serial, ',' ); rc &= DaoValue_Serialize2( node->key.pValue, serial, ns, proc, kt, buf, omap ); DString_AppendMBS( serial, sep ); rc &= DaoValue_Serialize2( node->value.pValue, serial, ns, proc, vt, buf, omap ); } return rc; }
static int DaoTuple_Serialize( DaoTuple *self, DString *serial, DaoNamespace *ns, DaoProcess *proc, DString *buf, DMap *omap ) { DArray *nested = self->unitype ? self->unitype->nested : NULL; int i, rc = 1; for(i=0; i<self->size; i++){ DaoType *type = NULL; DaoType *it = NULL; if( nested && nested->size > i ) type = nested->items.pType[i]; if( type && type->tid == DAO_PAR_NAMED ) type = & type->aux->xType; if( type && (type->tid == 0 || type->tid >= DAO_ENUM)) type = NULL; if( type == NULL ) it = DaoNamespace_GetType( ns, self->items[i] ); if( i ) DString_AppendChar( serial, ',' ); rc &= DaoValue_Serialize2( self->items[i], serial, ns, proc, it, buf, omap ); } return rc; }
static void Dao_AboutVar( DaoNamespace *ns, DaoValue *var, DString *str ) { DaoType *abtp = DaoNamespace_GetType( ns, var ); char buf[50]; if( abtp ){ DString_Append( str, abtp->name ); sprintf( buf, "[%p]", var ); DString_AppendMBS( str, buf ); if( var->type == DAO_CDATA ){ sprintf( buf, "(%p)", var->xCdata.data ); DString_AppendMBS( str, buf ); } }else{ DString_AppendMBS( str, "NULL" ); } }
static int DaoList_Serialize( DaoList *self, DString *serial, DaoNamespace *ns, DaoProcess *proc, DString *buf, DMap *omap ) { DaoType *type = self->unitype; int i, rc = 1; if( type->nested && type->nested->size ) type = type->nested->items.pType[0]; if( type && type->simtype == 0 && (type->tid == 0 || type->tid >= DAO_ENUM)) type = NULL; for(i=0; i<self->items.size; i++){ DaoType *it = NULL; if( type == NULL ) it = DaoNamespace_GetType( ns, self->items.items.pValue[i] ); if( i ) DString_AppendChar( serial, ',' ); if( it == NULL && type && type->tid >= DAO_ARRAY ) DString_AppendChar( serial, '{' ); rc &= DaoValue_Serialize2( self->items.items.pValue[i], serial, ns, proc, it, buf, omap ); if( it == NULL && type && type->tid >= DAO_ARRAY ) DString_AppendChar( serial, '}' ); } return rc; }
static DaoType* DaoInterface_CheckConversion( DaoType *self, DaoType *type, DaoRoutine *ctx ) { DaoRoutine *rout; DString *buffer = DString_NewChars( "(" ); DString_Append( buffer, type->name ); DString_AppendChars( buffer, ")" ); rout = DaoType_FindFunction( self, 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; } return NULL; }
static void DaoValue_BasicPrint( DaoValue *self, DaoProcess *proc, DaoStream *stream, DMap *cycData ) { DaoType *type = DaoNamespace_GetType( proc->activeNamespace, self ); if( self->type <= DAO_TUPLE ) DaoStream_WriteMBS( stream, coreTypeNames[ self->type ] ); else DaoStream_WriteMBS( stream, DaoValue_GetTyper( self )->name ); if( self->type == DAO_NONE ) return; if( self->type == DAO_TYPE ){ DaoStream_WriteMBS( stream, "<" ); DaoStream_WriteMBS( stream, self->xType.name->mbs ); DaoStream_WriteMBS( stream, ">" ); } DaoStream_WriteMBS( stream, "_" ); DaoStream_WriteInt( stream, self->type ); DaoStream_WriteMBS( stream, "_" ); DaoStream_WritePointer( stream, self ); if( self->type <= DAO_TUPLE ) return; if( type && self == type->value ) DaoStream_WriteMBS( stream, "[default]" ); }
static DaoType* DaoObject_CheckConversion( DaoType *self, DaoType *type, DaoRoutine *ctx ) { DString *buffer; DaoRoutine *rout; DaoType *hostype = ctx->routHost; DaoClass *host = hostype != NULL && hostype->tid == DAO_OBJECT ? (DaoClass*) hostype->aux : NULL; if( DaoType_ChildOf( self, type ) ) return type; if( DaoType_ChildOf( type, self ) ) return type; buffer = DString_NewChars( "(" ); DString_Append( buffer, type->name ); DString_AppendChars( buffer, ")" ); rout = DaoClass_FindMethod( (DaoClass*) self->aux, buffer->chars, host ); 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 != NULL ) return type; return NULL; }
static DaoType* DaoObject_CheckGetField( DaoType *self, DaoString *name, 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; if( data == NULL ){ error = DAO_ERROR_FIELD_ABSENT; }else if( data->type == DAO_NONE ){ error = DAO_ERROR_FIELD_HIDDEN; }else{ switch( data->xBase.subtype ){ case DAO_OBJECT_VARIABLE : return data->xVar.dtype; case DAO_CLASS_VARIABLE : return data->xVar.dtype; case DAO_CLASS_CONSTANT : return DaoNamespace_GetType( ctx->nameSpace, data->xConst.value ); } } if( error ){ DString *field = DString_NewChars( "." ); DString_Append( field, name->value ); rout = DaoClass_FindMethod( klass, field->chars, host ); DString_Delete( field ); if( rout != NULL ){ rout = DaoRoutine_MatchByType( rout, self, NULL, 0, DVM_CALL ); }else{ rout = DaoClass_FindMethod( klass, ".", host ); if( rout == NULL ) return NULL; rout = DaoRoutine_MatchByType( rout, self, & dao_type_string, 1, DVM_CALL ); } if( rout == NULL ) return NULL; return (DaoType*) rout->routType->aux; } return NULL; }
DaoType* DaoValue_CheckGetValueField( DaoType *self, DaoString *field, DaoRoutine *ctx ) { DaoValue *value = DaoType_FindValue( self, field->value ); if( value ) return DaoNamespace_GetType( ctx->nameSpace, value ); return NULL; }
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 ) ); }
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; }
DaoValue* DaoValue_DoGetValueField( DaoValue *self, DaoString *field, DaoProcess *proc ) { DaoType *type = DaoNamespace_GetType( proc->activeNamespace, self ); return DaoType_FindValue( type, field->value ); }