static DaoValue* DaoObject_DoGetField( DaoValue *self, DaoString *name, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoObject *host = proc->activeObject; DaoClass *hostClass = host ? host->defClass : NULL; DaoValue *value = NULL; int rc = DaoObject_GetData( object, name->value, & value, host ); if( rc ){ DaoRoutine *rout; DString *field = proc->string; DString_SetChars( field, "." ); DString_Append( field, name->value ); rout = DaoClass_FindMethod( object->defClass, field->chars, hostClass ); if( rout != NULL ){ rc = DaoProcess_PushCall( proc, rout, self, NULL, 0 ); }else{ DaoValue *arg = (DaoValue*) name; rout = DaoClass_FindMethod( object->defClass, ".", hostClass ); if( rout != NULL ) rc = DaoProcess_PushCall( proc, rout, self, & arg, 1 ); } if( rout == NULL ) return NULL; }else{ DaoProcess_PutValue( proc, value ); } if( rc ) DaoProcess_RaiseError( proc, daoExceptionNames[rc], name->value->chars ); return NULL; }
static int DaoObject_DoSetField( DaoValue *self, DaoString *name, DaoValue *value, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoObject *host = proc->activeObject; DaoClass *hostClass = host ? host->defClass : NULL; int ec = DaoObject_SetData( object, name->value, value, host ); if( ec != DAO_OK ){ DString *field = proc->string; DaoRoutine *rout; DString_SetChars( field, "." ); DString_Append( field, name->value ); DString_AppendChars( field, "=" ); rout = DaoClass_FindMethod( object->defClass, field->chars, hostClass ); if( rout != NULL ){ ec = DaoProcess_PushCall( proc, rout, self, & value, 1 ); }else{ DaoValue *args[2]; args[0] = (DaoValue*) name; args[1] = value; rout = DaoClass_FindMethod( object->defClass, ".=", hostClass ); if( rout == NULL ) return DAO_ERROR_FIELD_ABSENT; ec = DaoProcess_PushCall( proc, rout, self, args, 2 ); } if( rout == NULL ) return DAO_ERROR_FIELD_ABSENT; } if( ec ) DaoProcess_RaiseError( proc, daoExceptionNames[ec], name->value->chars ); return ec; }
DaoValue* DaoObject_DoBinary( DaoValue *self, DaoVmCode *op, DaoValue *args[2], DaoProcess *proc ) { DaoClass *host = proc->activeObject ? proc->activeObject->defClass : NULL; DaoRoutine *rout = NULL; DaoValue *selfvalue = NULL; DaoType *argtypes[2]; switch( op->code ){ case DVM_ADD : case DVM_SUB : case DVM_MUL : case DVM_DIV : case DVM_MOD : case DVM_POW : case DVM_BITAND : case DVM_BITOR : case DVM_BITXOR : case DVM_BITLFT : case DVM_BITRIT : case DVM_AND : case DVM_OR : case DVM_LT : case DVM_LE : case DVM_EQ : case DVM_NE : case DVM_IN : break; default: return NULL; } argtypes[0] = proc->activeTypes[ op->a ]; argtypes[1] = proc->activeTypes[ op->b ]; if( op->c == op->a ){ const char *name = DaoVmCode_GetCompoundOperator( op->code ); rout = DaoClass_FindMethod( self->xObject.defClass, name, host ); if( rout != NULL ){ DaoProcess_PushCallWithTypes( proc, rout, self, args+1, argtypes + 1, 1 ); return NULL; } } rout = DaoClass_FindMethod( self->xObject.defClass, DaoVmCode_GetOperator( op->code ), host ); if( rout == NULL ){ switch( op->code ){ case DVM_EQ : DaoProcess_PutBoolean( proc, args[0] == args[1] ); break; case DVM_NE : DaoProcess_PutBoolean( proc, args[0] != args[1] ); break; default: break; } return NULL; } if( op->c == op->a && self == args[0] ) selfvalue = self; if( op->c == op->b && self == args[1] ) selfvalue = self; DaoProcess_PushCallWithTypes( proc, rout, selfvalue, args, argtypes, 2 ); // TODO: retc; return NULL; }
void DaoObject_Print( DaoValue *self, DaoStream *stream, DMap *cycmap, DaoProcess *proc ) { int ec = 0; char buf[50]; DMap *inmap = cycmap; DaoObject *object = (DaoObject*) self; DaoValue *params[2]; DaoRoutine *meth; sprintf( buf, "[%p]", object ); if( self == object->defClass->objType->value ){ DaoStream_WriteString( stream, object->defClass->className ); DaoStream_WriteChars( stream, "[null]" ); return; } if( cycmap != NULL && DMap_Find( cycmap, object ) != NULL ){ DaoStream_WriteString( stream, object->defClass->className ); DaoStream_WriteChars( stream, buf ); return; } if( cycmap == NULL ) cycmap = DHash_New(0,0); DMap_Insert( cycmap, self, self ); DaoValue_Clear( & proc->stackValues[0] ); params[0] = (DaoValue*) dao_type_string; params[1] = (DaoValue*) stream; meth = DaoClass_FindMethod( object->defClass, "(string)", NULL ); if( meth ){ ec = DaoProcess_Call( proc, meth, self, params, 2 ); if( ec ) ec = DaoProcess_Call( proc, meth, self, params, 1 ); }else{ meth = DaoClass_FindMethod( object->defClass, "serialize", NULL ); if( meth ) ec = DaoProcess_Call( proc, meth, self, NULL, 0 ); } if( ec ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->string->chars, NULL ); }else if( meth && proc->stackValues[0] ){ DaoValue_Print( proc->stackValues[0], stream, cycmap, proc ); }else{ DaoStream_WriteString( stream, object->defClass->className ); DaoStream_WriteChars( stream, buf ); } if( inmap == NULL ) DMap_Delete( cycmap ); }
static DaoValue* DaoObject_DoGetItem( DaoValue *self, DaoValue *index[], int N, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoClass *host = proc->activeObject ? proc->activeObject->defClass : NULL; DaoRoutine *rout = DaoClass_FindMethod( object->defClass, "[]", host ); int rc = DaoProcess_PushCall( proc, rout, self, index, N ); if( rc ) DaoProcess_RaiseError( proc, daoExceptionNames[rc], NULL ); return NULL; }
DaoType* DaoObject_CheckBinary( DaoType *self, DaoVmCode *op, DaoType *args[2], DaoRoutine *ctx ) { DaoType *type = ctx->routHost; DaoClass *host = type != NULL && type->tid == DAO_OBJECT ? (DaoClass*) type->aux : NULL; DaoRoutine *rout = NULL; DaoType *selftype = NULL; switch( op->code ){ case DVM_ADD : case DVM_SUB : case DVM_MUL : case DVM_DIV : case DVM_MOD : case DVM_POW : case DVM_BITAND : case DVM_BITOR : case DVM_BITXOR : case DVM_BITLFT : case DVM_BITRIT : case DVM_AND : case DVM_OR : case DVM_LT : case DVM_LE : case DVM_EQ : case DVM_NE : case DVM_IN : break; default: return NULL; } if( op->c == op->a ){ const char *name = DaoVmCode_GetCompoundOperator( op->code ); rout = DaoClass_FindMethod( (DaoClass*) self->aux, name, host ); if( rout != NULL ){ rout = DaoRoutine_MatchByType( rout, self, args+1, 1, DVM_CALL ); if( rout == NULL ) return NULL; return (DaoType*) rout->routType->aux; } } rout = DaoClass_FindMethod( (DaoClass*) self->aux, DaoVmCode_GetOperator( op->code ), host ); if( rout == NULL ){ if( op->code == DVM_EQ || op->code == DVM_NE ) return dao_type_bool; return NULL; } if( op->c == op->a && self == args[0] ) selftype = self; if( op->c == op->b && self == args[1] ) selftype = self; rout = DaoRoutine_MatchByType( rout, selftype, args, 2, DVM_CALL ); if( rout == NULL ) return NULL; return (DaoType*) rout->routType->aux; }
static DaoType* DaoObject_CheckGetItem( DaoType *self, DaoType *index[], int N, DaoRoutine *ctx ) { DaoType *type = ctx->routHost; DaoClass *host = type != NULL && type->tid == DAO_OBJECT ? (DaoClass*) type->aux : NULL; DaoRoutine *rout = DaoClass_FindMethod( (DaoClass*) self->aux, "[]", host ); if( rout != NULL ) rout = DaoRoutine_MatchByType( rout, self, index, N, DVM_CALL ); if( rout == NULL ) return NULL; return (DaoType*) rout->routType->aux; }
int DaoObject_DoForEach( DaoValue *self, DaoTuple *iterator, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoClass *host = proc->activeObject ? proc->activeObject->defClass : NULL; DaoRoutine *rout = DaoClass_FindMethod( object->defClass, "for", host ); if( rout != NULL ){ return DaoProcess_PushCall( proc, rout, self, (DaoValue**) & iterator, 1 ); } return DAO_ERROR; }
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 DaoObject_Print( DaoValue *self0, DaoProcess *proc, DaoStream *stream, DMap *cycData ) { int ec = 0; char buf[50]; DaoObject *self = & self0->xObject; DaoValue *params[2]; DaoRoutine *meth; sprintf( buf, "[%p]", self ); if( self0 == self->defClass->objType->value ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, "[null]" ); return; } if( cycData != NULL && DMap_Find( cycData, self ) != NULL ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); return; } if( cycData ) MAP_Insert( cycData, self, self ); DaoValue_Clear( & proc->stackValues[0] ); params[0] = (DaoValue*) dao_type_string; params[1] = (DaoValue*) stream; meth = DaoClass_FindMethod( self->defClass, "(string)", NULL ); if( meth ){ ec = DaoProcess_Call( proc, meth, self0, params, 2 ); if( ec ) ec = DaoProcess_Call( proc, meth, self0, params, 1 ); }else{ meth = DaoClass_FindMethod( self->defClass, "serialize", NULL ); if( meth ) ec = DaoProcess_Call( proc, meth, self0, NULL, 0 ); } if( ec ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->string->chars, NULL ); }else if( meth && proc->stackValues[0] ){ DaoValue_Print( proc->stackValues[0], proc, stream, cycData ); }else{ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); } }
static int DaoObject_DoSetItem( DaoValue *self, DaoValue *index[], int N, DaoValue *value, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoClass *host = proc->activeObject ? proc->activeObject->defClass : NULL; DaoRoutine *rout = DaoClass_FindMethod( object->defClass, "[]=", host ); DaoValue *args[DAO_MAX_PARAM+1]; int rc; args[0] = value; memcpy( args+1, index, N*sizeof(DaoValue*) ); return DaoProcess_PushCall( proc, rout, self, args, N+1 ); //if( rc ) DaoProcess_RaiseError( proc, daoExceptionNames[rc], NULL ); }
static int DaoObject_CheckSetItem( DaoType *self, DaoType *index[], int N, DaoType *value, DaoRoutine *ctx ) { DaoType *type = ctx->routHost; DaoClass *host = type != NULL && type->tid == DAO_OBJECT ? (DaoClass*) type->aux : NULL; DaoRoutine *rout = DaoClass_FindMethod( (DaoClass*) self->aux, "[]=", host ); DaoType *args[ DAO_MAX_PARAM + 1 ]; args[0] = value; memcpy( args + 1, index, N*sizeof(DaoType*) ); if( rout != NULL ) rout = DaoRoutine_MatchByType( rout, self, args, N+1, DVM_CALL ); if( rout == NULL ) return DAO_ERROR_INDEX; return DAO_OK; }
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* DaoObject_CheckForEach( DaoType *self, DaoRoutine *ctx ) { DaoType *hostype = ctx->routHost; DaoClass *host = hostype != NULL && hostype->tid == DAO_OBJECT ? (DaoClass*) hostype->aux : NULL; DaoRoutine *rout = DaoClass_FindMethod( (DaoClass*) self->aux, "for", host ); if( rout != NULL ){ DaoType *type, *itype; if( rout->routType->args->size != 2 ) return NULL; type = rout->routType->args->items.pType[1]; if( type->tid == DAO_PAR_NAMED ) type = (DaoType*) type->aux; if( type->tid != DAO_TUPLE || type->args->size != 2 ) return NULL; itype = type->args->items.pType[0]; if( itype->tid != DAO_BOOLEAN ) return NULL; return DaoNamespace_MakeIteratorType( ctx->nameSpace, type->args->items.pType[1] ); } return NULL; }
static DaoValue* DaoObject_DoConversion( DaoValue *self, DaoType *type, int copy, DaoProcess *proc ) { DaoObject *object = (DaoObject*) self; DaoClass *host = proc->activeObject ? proc->activeObject->defClass : NULL; DaoValue *base = DaoObject_CastToBase( object->rootObject, type ); DaoRoutine *rout; DString *buffer; if( base ) return base; buffer = DString_NewChars( "(" ); DString_Append( buffer, type->name ); DString_AppendChars( buffer, ")" ); rout = DaoClass_FindMethod( object->defClass, buffer->chars, host ); DString_Delete( buffer ); if( rout != NULL ){ int rc = DaoProcess_PushCall( proc, rout, self, (DaoValue**) & type, 1 ); if( rc ) return NULL; } return NULL; }
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; }
DaoType* DaoObject_CheckUnary( DaoType *self, DaoVmCode *op, DaoRoutine *ctx ) { DaoType *type = ctx->routHost; DaoClass *host = type != NULL && type->tid == DAO_OBJECT ? (DaoClass*) type->aux : NULL; DaoRoutine *rout = NULL; switch( op->code ){ case DVM_NOT : case DVM_MINUS : case DVM_TILDE : case DVM_SIZE : break; default: return NULL; } rout = DaoClass_FindMethod( (DaoClass*) self->aux, DaoVmCode_GetOperator( op->code ), host ); if( rout == NULL ) return NULL; if( op->c == op->a ){ rout = DaoRoutine_MatchByType( rout, self, & self, 1, DVM_CALL ); }else{ rout = DaoRoutine_MatchByType( rout, NULL, & self, 1, DVM_CALL ); } if( rout == NULL ) return NULL; return (DaoType*) rout->routType->aux; }
DaoValue* DaoObject_DoUnary( DaoValue *self, DaoVmCode *op, DaoProcess *proc ) { DaoClass *host = proc->activeObject ? proc->activeObject->defClass : NULL; DaoType *argtype = proc->activeTypes[op->a];; DaoRoutine *rout = NULL; int retc = 0; switch( op->code ){ case DVM_NOT : case DVM_MINUS : case DVM_TILDE : case DVM_SIZE : break; default: return NULL; } rout = DaoClass_FindMethod( self->xObject.defClass, DaoVmCode_GetOperator( op->code ), host ); if( rout == NULL ) return NULL; if( op->c == op->a ){ retc = DaoProcess_PushCallWithTypes( proc, rout, self, & self, & argtype, 1 ); }else{ retc = DaoProcess_PushCallWithTypes( proc, rout, NULL, & self, & argtype, 1 ); } // TODO: retc; return NULL; }