int DaoObject_GetData( DaoObject *self, DString *name, DaoValue **data, DaoObject *othis ) { DNode *node; DaoValue *p = NULL; DaoClass *klass = self->defClass; DaoObject *null = & klass->objType->value->xObject; int child = othis && DaoObject_ChildOf( (DaoValue*)othis, (DaoValue*)self ); int id, st, up, pm, access; *data = NULL; node = DMap_Find( self->defClass->lookupTable, name ); if( node == NULL ) return DAO_ERROR_FIELD_NOTEXIST; pm = LOOKUP_PM( node->value.pInt ); st = LOOKUP_ST( node->value.pInt ); up = LOOKUP_UP( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( self == null && st == DAO_OBJECT_VARIABLE ) return DAO_ERROR_FIELD_NOTPERMIT; access = othis == self || pm == DAO_PERM_PUBLIC || (child && pm >= DAO_PERM_PROTECTED); if( access == 0 ) return DAO_ERROR_FIELD_NOTPERMIT; switch( st ){ case DAO_OBJECT_VARIABLE : p = self->objValues[id]; break; case DAO_CLASS_VARIABLE : p = klass->variables->items.pVar[id]->value; break; case DAO_CLASS_CONSTANT : p = klass->constants->items.pConst[id]->value; break; default : break; } *data = p; return 0; }
int DaoClass_GetData( DaoClass *self, DString *name, DaoValue **value, DaoClass *thisClass ) { DaoValue *p = NULL; DNode *node = MAP_Find( self->lookupTable, name ); int child = thisClass && DaoClass_ChildOf( thisClass, (DaoValue*)self ); int sto, perm, up, id; *value = NULL; if( ! node ) return DAO_ERROR_FIELD_NOTEXIST; perm = LOOKUP_PM( node->value.pInt ); sto = LOOKUP_ST( node->value.pInt ); up = LOOKUP_UP( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( self == thisClass || perm == DAO_DATA_PUBLIC || (child && perm >= DAO_DATA_PROTECTED) ){ switch( sto ){ case DAO_CLASS_VARIABLE : p = self->variables->items.pVar[id]->value; break; case DAO_CLASS_CONSTANT : p = self->constants->items.pConst[id]->value; break; default : return DAO_ERROR_FIELD; } if( p ) *value = p; }else{ return DAO_ERROR_FIELD_NOTPERMIT; } return 0; }
int DaoClass_AddGlobalVar( DaoClass *self, DString *name, DaoValue *data, DaoType *t, int s ) { int size = self->variables->size; int id = LOOKUP_BIND( DAO_CLASS_VARIABLE, s, 0, size ); DNode *node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; if( data == NULL && t ) data = t->value; MAP_Insert( self->lookupTable, name, id ); DArray_Append( self->variables, DaoVariable_New( NULL, t ) ); DArray_Append( self->glbDataName, (void*)name ); if( data && DaoValue_Move( data, & self->variables->items.pVar[size]->value, t ) ==0 ) return -DAO_CTW_TYPE_NOMATCH; return id; }
int DaoClass_AddObjectVar( DaoClass *self, DString *name, DaoValue *deft, DaoType *t, int s ) { int id; DNode *node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; if( deft == NULL && t ) deft = t->value; id = self->objDataName->size; MAP_Insert( self->lookupTable, name, LOOKUP_BIND( DAO_OBJECT_VARIABLE, s, 0, id ) ); DArray_Append( self->objDataName, (void*)name ); DArray_Append( self->instvars, DaoVariable_New( deft, t ) ); DaoValue_MarkConst( self->instvars->items.pVar[ id ]->value ); return id; }
static void DaoClass_SetField( DaoValue *self0, DaoProcess *proc, DString *name, DaoValue *value ) { DaoClass *self = & self0->xClass; DNode *node = DMap_Find( self->lookupTable, name ); if( node && LOOKUP_ST( node->value.pInt ) == DAO_CLASS_VARIABLE ){ int up = LOOKUP_UP( node->value.pInt ); int id = LOOKUP_ID( node->value.pInt ); DaoVariable *dt = self->variables->items.pVar[id]; if( DaoValue_Move( value, & dt->value, dt->dtype ) ==0 ) DaoProcess_RaiseException( proc, DAO_ERROR_PARAM, "not matched" ); }else{ /* XXX permission */ DaoProcess_RaiseException( proc, DAO_ERROR_FIELD, "not exist" ); } }
int DaoObject_SetData( DaoObject *self, DString *name, DaoValue *data, DaoObject *othis ) { DNode *node; DaoType *type; DaoValue **value ; DaoClass *klass = self->defClass; DaoObject *null = & klass->objType->value->xObject; int child = othis && DaoObject_ChildOf( (DaoValue*)othis, (DaoValue*)self ); int id, st, up, pm, access; if( self == (DaoObject*)self->defClass->objType->value ) return DAO_ERROR; node = DMap_Find( self->defClass->lookupTable, name ); if( node == NULL ) return DAO_ERROR_FIELD_NOTEXIST; pm = LOOKUP_PM( node->value.pInt ); st = LOOKUP_ST( node->value.pInt ); up = LOOKUP_UP( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( self == null && st == DAO_OBJECT_VARIABLE ) return DAO_ERROR_FIELD_NOTPERMIT; access = othis == self || pm == DAO_PERM_PUBLIC || (child && pm >= DAO_PERM_PROTECTED); if( access == 0 ) return DAO_ERROR_FIELD_NOTPERMIT; if( st == DAO_OBJECT_VARIABLE ){ if( id <0 ) return DAO_ERROR_FIELD_NOTPERMIT; type = klass->instvars->items.pVar[ id ]->dtype; value = self->objValues + id; if( DaoValue_Move( data, value, type ) ==0 ) return DAO_ERROR_VALUE; }else if( st == DAO_CLASS_VARIABLE ){ DaoVariable *var = klass->variables->items.pVar[id]; if( DaoValue_Move( data, & var->value, var->dtype ) ==0 ) return DAO_ERROR_VALUE; }else if( st == DAO_CLASS_CONSTANT ){ return DAO_ERROR_FIELD; }else{ return DAO_ERROR_FIELD; } return 0; }
static void NS_Backup( DaoNamespace *self, DaoProcess *proc, FILE *fout, int limit, int store ) { DNode *node = DMap_First( self->lookupTable ); DString *prefix = DString_New(1); DString *serial = DString_New(1); DaoValue *value = NULL; size_t max = limit * 1000; /* limit per object in KB */ int id, pm, up, st; for( ; node !=NULL; node = DMap_Next( self->lookupTable, node ) ){ DString *name = node->key.pString; id = node->value.pInt; up = LOOKUP_UP( id ); st = LOOKUP_ST( id ); pm = LOOKUP_PM( id ); if( up ) continue; if( st != store ) continue; if( st == DAO_GLOBAL_CONSTANT ) value = DaoNamespace_GetConst( self, id ); if( st == DAO_GLOBAL_VARIABLE ) value = DaoNamespace_GetVariable( self, id ); if( value == NULL ) continue; if( DaoValue_Serialize( value, serial, self, proc ) ==0 ) continue; prefix->size = 0; switch( pm ){ case DAO_DATA_PRIVATE : DString_AppendMBS( prefix, "private " ); break; case DAO_DATA_PROTECTED : DString_AppendMBS( prefix, "protected " ); break; case DAO_DATA_PUBLIC : DString_AppendMBS( prefix, "public " ); break; } switch( st ){ case DAO_GLOBAL_CONSTANT : DString_AppendMBS( prefix, "const " ); break; case DAO_GLOBAL_VARIABLE : DString_AppendMBS( prefix, "var " ); break; } if( max && prefix->size + name->size + serial->size + 4 > max ) continue; fprintf( fout, "%s%s = %s\n", prefix->mbs, name->mbs, serial->mbs ); } DString_Delete( prefix ); DString_Delete( serial ); }
/* assumed to be called before parsing class body */ int DaoClass_DeriveClassData( DaoClass *self ) { DaoType *type; DaoValue *value; DString *mbs; DNode *it, *search; DaoMethodFields *mf; daoint i, j, k, id; if( DaoCass_DeriveMixinData( self ) == 0 ) return 0; mbs = DString_New(1); mf = DaoMethodFields_New(); if( self->clsType->bases == NULL ) self->clsType->bases = DArray_New(D_VALUE); if( self->objType->bases == NULL ) self->objType->bases = DArray_New(D_VALUE); DArray_Clear( self->clsType->bases ); DArray_Clear( self->objType->bases ); self->cstParentStart = self->constants->size; self->glbParentStart = self->variables->size; DVector_PushUshort( self->offsets, self->constants->size ); DVector_PushUshort( self->offsets, self->variables->size ); if( self->parent && self->parent->type == DAO_CLASS ){ DaoClass *klass = (DaoClass*) self->parent; DArray_Append( self->clsType->bases, klass->clsType ); DArray_Append( self->objType->bases, klass->objType ); DArray_AppendArray( self->cstDataName, klass->cstDataName ); DArray_AppendArray( self->glbDataName, klass->glbDataName ); for(j=0; j<klass->constants->size; ++j){ DaoValue *cst = klass->constants->items.pConst[j]->value; DArray_Append( self->constants, klass->constants->items.pVoid[j] ); } for(j=0; j<klass->variables->size; ++j){ DArray_Append( self->variables, klass->variables->items.pVoid[j] ); } for(it=DMap_First(klass->lookupTable); it; it=DMap_Next(klass->lookupTable,it)){ daoint pm = LOOKUP_PM( it->value.pInt ); daoint st = LOOKUP_ST( it->value.pInt ); daoint up = LOOKUP_UP( it->value.pInt ); daoint id = LOOKUP_ID( it->value.pInt ); DaoValue *cst; if( st == DAO_CLASS_CONSTANT ){ id = LOOKUP_ID( it->value.pInt ); cst = klass->constants->items.pConst[id]->value; if( cst->type == DAO_ROUTINE ){ DArray_Append( mf->names, it->key.pString ); DArray_Append( mf->perms, IntToPointer( pm ) ); DArray_Append( mf->routines, cst ); } } if( st == DAO_OBJECT_VARIABLE ) continue; if( pm == DAO_DATA_PRIVATE ) continue; if( DMap_Find( self->lookupTable, it->key.pString ) ) continue; switch( st ){ case DAO_CLASS_CONSTANT : id += self->cstParentStart; break; case DAO_CLASS_VARIABLE : id += self->glbParentStart; break; case DAO_OBJECT_VARIABLE : continue; } id = LOOKUP_BIND( st, pm, up+1, id ); DMap_Insert( self->lookupTable, it->key.pString, (void*)id ); } }else if( self->parent && self->parent->type == DAO_CTYPE ){ DaoCtype *cdata = (DaoCtype*) self->parent; DaoTypeKernel *kernel = cdata->ctype->kernel; DaoTypeBase *typer = kernel->typer; DMap *methods = kernel->methods; DMap *values = kernel->values; DArray_Append( self->clsType->bases, cdata->ctype ); DArray_Append( self->objType->bases, cdata->cdtype ); DaoClass_AddConst( self, cdata->ctype->name, (DaoValue*)cdata, DAO_DATA_PUBLIC ); if( kernel->SetupValues ) kernel->SetupValues( kernel->nspace, kernel->typer ); if( kernel->SetupMethods ) kernel->SetupMethods( kernel->nspace, kernel->typer ); DaoCdataType_SpecializeMethods( cdata->ctype ); kernel = cdata->ctype->kernel; values = kernel->values; methods = kernel->methods; if( typer->numItems ){ for(j=0; typer->numItems[j].name!=NULL; j++){ DString name = DString_WrapMBS( typer->numItems[j].name ); it = DMap_Find( values, & name ); if( it == NULL ) continue; if( DMap_Find( self->lookupTable, it->key.pString ) ) continue; id = self->constants->size; id = LOOKUP_BIND( DAO_CLASS_CONSTANT, DAO_DATA_PUBLIC, 1, id ); DMap_Insert( self->lookupTable, it->key.pString, IntToPointer( id ) ); DArray_Append( self->cstDataName, it->key.pString ); DArray_Append( self->constants, DaoConstant_New( it->value.pValue ) ); } } for(it=DMap_First( methods ); it; it=DMap_Next( methods, it )){ if( DMap_Find( self->lookupTable, it->key.pString ) ) continue; id = self->constants->size; id = LOOKUP_BIND( DAO_CLASS_CONSTANT, DAO_DATA_PUBLIC, 1, id ); DMap_Insert( self->lookupTable, it->key.pString, IntToPointer( id ) ); DArray_Append( self->cstDataName, it->key.pString ); DArray_Append( self->constants, DaoConstant_New( it->value.pValue ) ); DArray_Append( mf->names, it->key.pString ); DArray_Append( mf->perms, IntToPointer( DAO_DATA_PUBLIC ) ); DArray_Append( mf->routines, it->value.pValue ); } } DaoClass_SetupMethodFields( self, mf ); DaoMethodFields_Delete( mf ); self->cstParentEnd = self->constants->size; self->glbParentEnd = self->variables->size; #if 0 for(j=0; j<self->constants->size; ++j){ DaoValue *value = self->constants->items.pConst[j]->value; DaoRoutine *routine = (DaoRoutine*) value; printf( "%3i: %3i %s\n", j, value->type, self->cstDataName->items.pString[j]->mbs ); if( value->type != DAO_ROUTINE ) continue; printf( "%3i: %3i %s\n", j, value->type, routine->routName->mbs ); if( routine->overloads ){ DArray *routs = routine->overloads->routines; for(k=0; k<routs->size; ++k){ DaoRoutine *rout = routs->items.pRoutine[k]; } }else{ if( routine->attribs & DAO_ROUT_PRIVATE ) continue; } } for(it=DMap_First(self->lookupTable); it; it=DMap_Next(self->lookupTable,it)){ printf( "%s %i\n", it->key.pString->mbs, it->value.pInt ); if( LOOKUP_ST( it->value.pInt ) != DAO_CLASS_CONSTANT ) continue; DaoValue *value = DaoClass_GetConst( self, it->value.pInt ); printf( "%i\n", value->type ); } #endif DString_Delete( mbs ); return 1; }
/* // The layout of mixins in a host class: // 1. Each mixin occupies a continuous segment in the data arrays of the host. // The ranges of the segments are stored in DaoClass::ranges; // 2. If the mixin contains other mixins, those mixins occupy segments preceding // the segment for this mixin; // 3. The segments for the direct mixins of the host are arranged in the same // order as the mixins; // // For example, there are the following mixins: // class AA { var x = 1 } // class BB { var x = 1 } // class CC ( AA, BB ) { var x = 1 } // class DD ( CC, AA ) { var x = 1 } // The mixin layout for CC: // CC_Header, AA_Header, AA_Data, BB_Header, BB_Data, CC_Data // The mixin layout for DD: // DD_Header, AA_Header, AA_Data, BB_Header, BB_Data, CC_Header, CC_Data, DD_Data // // Where XX_Header are the data fields that are always placed at the header // of the data array. For example, XX_Header for class constants contains // two fields: one for the class itself, the other for the class constructor(s); // XX_Header for class static variables is empty; and XX_Header for class // instance variables contains only the field for the "self" variable. // And XX_Data constains the mixin's own data which are not from its // component mixins or from its paraent classes (actually only classes // without parent classes can be used as mixins). // // // To mix a mixin in the host class, the mixin (and its component mixins if any) // are properly arranged in the host class with layouts described above. // The non-trivial part is the update of variable types and the methods // that are added to the host class from the mixin. To update the types, // the type for the mixin are all replaced with the type for the host class. // // The update of methods involves three major steps: // 1. Update the routine signature type, local variable types and the static // variable types; // 2. Update the lookup table of the host class for the data from the mixins, // which is done by mapping the indices for the mixin data arrays to the // indices for the host data arrays; // 3. Update the method code (VM instructions) such that operands involving // class or class instance data are properly mapped from the indices for // the mixin data arrays to the indices for the host data arrays. */ static int DaoClass_MixIn( DaoClass *self, DaoClass *mixin, DMap *mixed, DaoMethodFields *mf ) { daoint i, j, k, id, bl = 1; DaoNamespace *ns = self->classRoutine->nameSpace; DArray *routines; DMap *deftypes; DMap *routmap; DMap *idmap; DNode *it; if( mixin->parent != NULL ) return 0; if( DMap_Find( mixed, mixin ) != NULL ) return 1; /* Mix the component mixins first: */ for(i=0; i<mixin->mixinBases->size; ++i){ DaoClass *mx = mixin->mixinBases->items.pClass[i]; bl = bl && DaoClass_MixIn( self, mx, mixed, mf ); } if( bl == 0 ) return 0; idmap = DMap_New(0,0); routmap = DMap_New(0,0); deftypes = DMap_New(0,0); routines = DArray_New(0); DMap_Insert( mixed, mixin, idmap ); DMap_Delete( idmap ); idmap = DMap_Find( mixed, mixin )->value.pMap; /* Add this mixin to the mixin list for both direct and indirect mixins: */ DArray_Append( self->mixins, mixin ); /* Save the starts of the ranges for this mixin in the host class: */ DVector_PushUshort( self->ranges, self->constants->size ); DVector_PushUshort( self->ranges, self->variables->size ); DVector_PushUshort( self->ranges, self->instvars->size ); /* For updating the types for the mixin to the types for the host class: */ DMap_Insert( deftypes, mixin->clsType, self->clsType ); DMap_Insert( deftypes, mixin->objType, self->objType ); #if 0 printf( "MixIn: %s %p %i\n", mixin->className->mbs, mixin, mixin->cstDataName->size ); #endif /* Add the own constants of the mixin to the host class: */ for(i=0; i<mixin->cstDataName->size; ++i){ daoint src = LOOKUP_BIND( DAO_CLASS_CONSTANT, 0, 0, i ); daoint des = LOOKUP_BIND( DAO_CLASS_CONSTANT, 0, 0, self->constants->size ); DString *name = mixin->cstDataName->items.pString[i]; DaoValue *value = mixin->constants->items.pConst[i]->value; DaoRoutine *rout = (DaoRoutine*) value; if( i >= mixin->cstMixinStart && i < mixin->cstMixinEnd2 ) continue; MAP_Insert( idmap, src, des ); /* Setup index mapping; */ DArray_Append( self->cstDataName, (void*) name ); if( value->type != DAO_ROUTINE || rout->routHost != mixin->objType ){ DaoConstant *cst = DaoConstant_New( value ); DArray_Append( self->constants, cst ); continue; } if( rout->overloads == NULL ){ DaoRoutine *old = rout; rout = DaoRoutine_Copy( rout, 1, 1, 1 ); bl = bl && DaoRoutine_Finalize( rout, self->objType, deftypes ); #if 0 printf( "%2i: %s %s\n", i, rout->routName->mbs, rout->routType->name->mbs ); #endif /* // Do not use DaoClass_AddConst() here, so that the original // method overloading structures will be mantained, without // interference from methods of other mixin component classes // or of the host class. */ it = DMap_Find( routmap, old ); if( it ) DRoutines_Add( it->value.pRoutine->overloads, rout ); DArray_Append( self->constants, DaoConstant_New( (DaoValue*) rout ) ); DArray_Append( routines, rout ); if( bl == 0 ) goto Finalize; }else{ /* No need to added the overloaded routines now; */ /* Each of them has an entry in constants, and will be handled later: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, NULL ); routs->trait |= DAO_VALUE_CONST; DArray_Append( self->constants, DaoConstant_New( (DaoValue*) routs ) ); for(j=0; j<rout->overloads->routines->size; ++j){ DaoRoutine *R = rout->overloads->routines->items.pRoutine[j]; DMap_Insert( routmap, R, routs ); } } } for(i=mixin->glbMixinEnd2; i<mixin->glbDataName->size; ++i){ daoint src = LOOKUP_BIND( DAO_CLASS_VARIABLE, 0, 0, i ); daoint des = LOOKUP_BIND( DAO_CLASS_VARIABLE, 0, 0, self->variables->size ); DString *name = mixin->glbDataName->items.pString[i]; DaoValue *var = mixin->variables->items.pVar[i]->value; DaoType *type = mixin->variables->items.pVar[i]->dtype; type = DaoType_DefineTypes( type, ns, deftypes ); MAP_Insert( idmap, src, des ); DArray_Append( self->glbDataName, (void*) name ); DArray_Append( self->variables, DaoVariable_New( var, type ) ); } for(i=mixin->objMixinEnd2; i<mixin->objDataName->size; ++i){ daoint src = LOOKUP_BIND( DAO_OBJECT_VARIABLE, 0, 0, i ); daoint des = LOOKUP_BIND( DAO_OBJECT_VARIABLE, 0, 0, self->instvars->size ); DString *name = mixin->objDataName->items.pString[i]; DaoValue *var = mixin->instvars->items.pVar[i]->value; DaoType *type = mixin->instvars->items.pVar[i]->dtype; type = DaoType_DefineTypes( type, ns, deftypes ); MAP_Insert( idmap, src, des ); DArray_Append( self->objDataName, (void*) name ); DArray_Append( self->instvars, DaoVariable_New( var, type ) ); } /* Find the ends of own data of this mixin: */ DVector_PushUshort( self->ranges, self->constants->size ); DVector_PushUshort( self->ranges, self->variables->size ); DVector_PushUshort( self->ranges, self->instvars->size ); /* Update the lookup table: */ for(it=DMap_First(mixin->lookupTable); it; it=DMap_Next(mixin->lookupTable,it)){ int pm = LOOKUP_PM( it->value.pInt ); int st = LOOKUP_ST( it->value.pInt ); int up = LOOKUP_UP( it->value.pInt ); int id = LOOKUP_ID( it->value.pInt ); DaoValue *cst; /* Skip names from component mixins (because they have been handled): */ switch( st ){ case DAO_CLASS_CONSTANT : if( id >= mixin->cstMixinStart && id < mixin->cstMixinEnd2 ) continue; break; case DAO_CLASS_VARIABLE : if( id >= mixin->glbMixinStart && id < mixin->glbMixinEnd2 ) continue; break; case DAO_OBJECT_VARIABLE : if( id >= mixin->objMixinStart && id < mixin->objMixinEnd2 ) continue; break; } if( st != DAO_OBJECT_VARIABLE || id != 0 ){ /* not a "self": */ DNode *it2 = MAP_Find( idmap, LOOKUP_BIND( st, 0, 0, id ) ); if( it2 ) id = LOOKUP_ID( it2->value.pInt ); /* map index; */ } MAP_Insert( self->lookupTable, it->key.pString, LOOKUP_BIND( st, pm, up, id ) ); if( st != DAO_CLASS_CONSTANT ) continue; cst = self->constants->items.pConst[id]->value; if( cst->type != DAO_ROUTINE ) continue; DArray_Append( mf->names, it->key.pString ); DArray_Append( mf->perms, IntToPointer( pm ) ); DArray_Append( mf->routines, cst ); } for(i=0; i<routines->size; i++){ DaoRoutine *rout = routines->items.pRoutine[i]; DaoType **types; if( rout->body == NULL ) continue; //DaoRoutine_PrintCode( rout, rout->nameSpace->vmSpace->stdioStream ); types = rout->body->regType->items.pType; for(j=0; j<rout->body->annotCodes->size; ++j){ DaoVmCodeX *vmc = rout->body->annotCodes->items.pVmc[j]; DaoClass *klass; DString *name; switch( vmc->code ){ case DVM_GETCK: case DVM_GETCK_I: case DVM_GETCK_F: case DVM_GETCK_D: case DVM_GETCK_C: vmc->b = DaoClass_MapIndex( mixin, DAO_CLASS_CONSTANT, vmc->b, mixed ); break; case DVM_GETVK: case DVM_GETVK_I: case DVM_GETVK_F: case DVM_GETVK_D: case DVM_GETVK_C: case DVM_SETVK: case DVM_SETVK_II: case DVM_SETVK_FF: case DVM_SETVK_DD: case DVM_SETVK_CC: vmc->b = DaoClass_MapIndex( mixin, DAO_CLASS_VARIABLE, vmc->b, mixed ); break; case DVM_GETVO: case DVM_GETVO_I: case DVM_GETVO_F: case DVM_GETVO_D: case DVM_GETVO_C: case DVM_SETVO: case DVM_SETVO_II: case DVM_SETVO_FF: case DVM_SETVO_DD: case DVM_SETVO_CC: vmc->b = DaoClass_MapIndex( mixin, DAO_OBJECT_VARIABLE, vmc->b, mixed ); break; case DVM_GETF_KC: case DVM_GETF_KCI: case DVM_GETF_KCF: case DVM_GETF_KCD: case DVM_GETF_KCC: case DVM_GETF_OC: case DVM_GETF_OCI: case DVM_GETF_OCF: case DVM_GETF_OCD: case DVM_GETF_OCC: klass = (DaoClass*) types[ vmc->a ]->aux; name = DaoClass_GetDataName( klass, DAO_CLASS_CONSTANT, vmc->b ); vmc->b = DaoRoutine_GetFieldIndex( rout, name ); vmc->code = DVM_GETF; break; case DVM_GETF_KG: case DVM_GETF_KGI: case DVM_GETF_KGF: case DVM_GETF_KGD: case DVM_GETF_KGC: case DVM_GETF_OG: case DVM_GETF_OGI: case DVM_GETF_OGF: case DVM_GETF_OGD: case DVM_GETF_OGC: klass = (DaoClass*) types[ vmc->a ]->aux; name = DaoClass_GetDataName( klass, DAO_CLASS_VARIABLE, vmc->b ); vmc->b = DaoRoutine_GetFieldIndex( rout, name ); vmc->code = DVM_GETF; break; case DVM_GETF_OV: case DVM_GETF_OVI: case DVM_GETF_OVF: case DVM_GETF_OVD: case DVM_GETF_OVC: klass = (DaoClass*) types[ vmc->a ]->aux; name = DaoClass_GetDataName( klass, DAO_OBJECT_VARIABLE, vmc->b ); vmc->b = DaoRoutine_GetFieldIndex( rout, name ); vmc->code = DVM_GETF; break; case DVM_SETF_KG: case DVM_SETF_KGII: case DVM_SETF_KGFF: case DVM_SETF_KGDD: case DVM_SETF_KGCC: case DVM_SETF_OG: case DVM_SETF_OGII: case DVM_SETF_OGFF: case DVM_SETF_OGDD: case DVM_SETF_OGCC: klass = (DaoClass*) types[ vmc->c ]->aux; name = DaoClass_GetDataName( klass, DAO_CLASS_VARIABLE, vmc->b ); vmc->b = DaoRoutine_GetFieldIndex( rout, name ); vmc->code = DVM_SETF; break; case DVM_SETF_OV: case DVM_SETF_OVII: case DVM_SETF_OVFF: case DVM_SETF_OVDD: case DVM_SETF_OVCC: klass = (DaoClass*) types[ vmc->c ]->aux; name = DaoClass_GetDataName( klass, DAO_OBJECT_VARIABLE, vmc->b ); vmc->b = DaoRoutine_GetFieldIndex( rout, name ); vmc->code = DVM_SETF; break; } } //DaoRoutine_PrintCode( rout, rout->nameSpace->vmSpace->stdioStream ); bl = bl && DaoRoutine_DoTypeInference( rout, 0 ); if( bl == 0 ) goto Finalize; } Finalize: DArray_Delete( routines ); DMap_Delete( routmap ); DMap_Delete( deftypes ); return bl; }
int DaoClass_AddConst( DaoClass *self, DString *name, DaoValue *data, int s ) { int fromMixin = 0; int fromParent = 0; int sto, pm, up, id; DNode *node = MAP_Find( self->lookupTable, name ); DaoNamespace *ns = self->classRoutine->nameSpace; DaoConstant *dest; DaoValue *value; if( node ){ id = LOOKUP_ID( node->value.pInt ); fromParent = LOOKUP_UP( node->value.pInt ); /* From parent classes; */ switch( LOOKUP_ST( node->value.pInt ) ){ /* Check if it is from mixins; */ case DAO_CLASS_CONSTANT : fromMixin = id >= self->cstMixinStart && id < self->cstMixinEnd; break; case DAO_CLASS_VARIABLE : fromMixin = id >= self->glbMixinStart && id < self->glbMixinEnd; break; case DAO_OBJECT_VARIABLE : fromMixin = id >= self->objMixinStart && id < self->objMixinEnd; break; } } assert( data != NULL ); if( fromParent || fromMixin ){ /* inherited field: */ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ){ /* override inherited variable: */ DMap_EraseNode( self->lookupTable, node ); return DaoClass_AddConst( self, name, data, s ); } node->value.pInt = LOOKUP_BIND( sto, pm, 0, id ); dest = self->constants->items.pConst[id]; if( dest->value->type == DAO_ROUTINE && data->type == DAO_ROUTINE ){ /* Add the inherited routine(s) for overloading: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*)dest->value ); DaoConstant *cst = DaoConstant_New( (DaoValue*) routs ); routs->trait |= DAO_VALUE_CONST; node->value.pInt = LOOKUP_BIND( sto, pm, 0, self->constants->size ); DArray_Append( self->cstDataName, (void*) name ); DArray_Append( self->constants, cst ); return DaoClass_AddConst( self, name, data, s ); }else{ /* Add the new constant: */ DaoConstant *cst = DaoConstant_New( data ); node->value.pInt = LOOKUP_BIND( sto, pm, 0, self->constants->size ); DArray_Append( self->cstDataName, (void*) name ); DArray_Append( self->constants, cst ); return node->value.pInt; } }else if( node ){ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ) return -DAO_CTW_WAS_DEFINED; dest = self->constants->items.pConst[id]; value = dest->value; if( value->type != DAO_ROUTINE || data->type != DAO_ROUTINE ) return -DAO_CTW_WAS_DEFINED; if( s > pm ) node->value.pInt = LOOKUP_BIND( sto, s, 0, id ); if( value->xRoutine.overloads == NULL || value->xRoutine.routHost != self->objType ){ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) value ); routs->trait |= DAO_VALUE_CONST; /* Add individual entry for the existing function: */ if( value->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, value ); GC_ShiftRC( routs, dest->value ); dest->value = (DaoValue*) routs; } if( data->xRoutine.overloads ){ DaoRoutines_Import( (DaoRoutine*) dest->value, data->xRoutine.overloads ); }else{ DaoRoutine *rout = (DaoRoutine*) data; DRoutines_Add( dest->value->xRoutine.overloads, rout ); /* Add individual entry for the new function: */ if( data->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, data ); } return node->value.pInt; } node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; return DaoClass_AddConst2( self, name, data, s ); }
int DaoClass_AddConst( DaoClass *self, DString *name, DaoValue *data, int s ) { int sto, pm, up, id; DNode *node = MAP_Find( self->lookupTable, name ); DaoNamespace *ns = self->classRoutine->nameSpace; DaoConstant *dest; DaoValue *value; assert( data != NULL ); if( node && LOOKUP_UP( node->value.pInt ) ){ /* inherited field: */ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ){ /* override inherited variable: */ DMap_EraseNode( self->lookupTable, node ); return DaoClass_AddConst( self, name, data, s ); } node->value.pInt = LOOKUP_BIND( sto, pm, 0, id ); dest = self->constants->items.pConst[id]; if( dest->value->type == DAO_ROUTINE && data->type == DAO_ROUTINE ){ /* Add the inherited routine(s) for overloading: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) dest->value ); DaoConstant *cst = DaoConstant_New( (DaoValue*) routs ); GC_ShiftRC( cst, dest ); self->constants->items.pConst[id] = cst; return DaoClass_AddConst( self, name, data, s ); }else{ /* Add the new constant: */ DaoConstant *cst = DaoConstant_New( data ); GC_ShiftRC( cst, dest ); self->constants->items.pConst[id] = cst; return node->value.pInt; } }else if( node ){ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ) return -DAO_CTW_WAS_DEFINED; dest = self->constants->items.pConst[id]; value = dest->value; if( value->type != DAO_ROUTINE || data->type != DAO_ROUTINE ) return -DAO_CTW_WAS_DEFINED; if( s > pm ) node->value.pInt = LOOKUP_BIND( sto, s, 0, id ); if( value->xRoutine.overloads == NULL || value->xRoutine.routHost != self->objType ){ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) value ); routs->trait |= DAO_VALUE_CONST; /* Add individual entry for the existing function: */ if( value->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, value ); GC_ShiftRC( routs, dest->value ); dest->value = (DaoValue*) routs; } if( data->xRoutine.overloads ){ DaoRoutines_Import( (DaoRoutine*) dest->value, data->xRoutine.overloads ); }else{ DaoRoutine *rout = (DaoRoutine*) data; DRoutines_Add( dest->value->xRoutine.overloads, rout ); if( self->vtable ) DaoRoutine_UpdateVtable( (DaoRoutine*)dest->value, rout, self->vtable ); /* Add individual entry for the new function: */ if( data->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, data ); } return node->value.pInt; } node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; return DaoClass_AddConst2( self, name, data, s ); }
int DaoClass_CopyField( DaoClass *self, DaoClass *other, DMap *deftypes ) { DaoNamespace *ns = other->classRoutine->nameSpace; DaoType *tp; DArray *offsets = DArray_New(0); DArray *routines = DArray_New(0); DNode *it; int i, k, st, up, id; for(i=0; i<other->superClass->size; i++){ DaoValue *sup = other->superClass->items.pValue[i]; if( sup->type == DAO_CLASS && sup->xClass.typeHolders ){ tp = DaoType_DefineTypes( sup->xClass.objType, ns, deftypes ); DArray_Append( self->superClass, tp->aux ); }else if( sup->type == DAO_CTYPE && sup->xCtype.ctype->typer->core->kernel->sptree ){ tp = DaoType_DefineTypes( sup->xCtype.ctype, ns, deftypes ); DArray_Append( self->superClass, tp->aux ); }else{ DArray_Append( self->superClass, sup ); } } DaoRoutine_CopyFields( self->classRoutine, other->classRoutine, 1, 1 ); for(it=DMap_First(other->lookupTable);it;it=DMap_Next(other->lookupTable,it)){ st = LOOKUP_ST( it->value.pInt ); up = LOOKUP_UP( it->value.pInt ); id = LOOKUP_ID( it->value.pInt ); if( up ==0 ){ if( st == DAO_CLASS_CONSTANT && id <self->constants->size ) continue; if( st == DAO_CLASS_VARIABLE && id <self->variables->size ) continue; if( st == DAO_OBJECT_VARIABLE && id <self->instvars->size ) continue; } DMap_Insert( self->lookupTable, it->key.pVoid, it->value.pVoid ); } for(i=self->objDataName->size; i<other->objDataName->size; i++) DArray_Append( self->objDataName, other->objDataName->items.pString[i] ); for(i=self->cstDataName->size; i<other->cstDataName->size; i++) DArray_Append( self->cstDataName, other->cstDataName->items.pString[i] ); for(i=self->glbDataName->size; i<other->glbDataName->size; i++) DArray_Append( self->glbDataName, other->glbDataName->items.pString[i] ); for(i=self->variables->size; i<other->variables->size; i++){ DaoVariable *var = other->variables->items.pVar[i]; var = DaoVariable_New( var->value, DaoType_DefineTypes( var->dtype, ns, deftypes ) ); DArray_Append( self->variables, var ); } for(i=self->instvars->size; i<other->instvars->size; i++){ DaoVariable *var = other->instvars->items.pVar[i]; var = DaoVariable_New( var->value, DaoType_DefineTypes( var->dtype, ns, deftypes ) ); DArray_Append( self->instvars, var ); /* TODO fail checking */ } for(i=self->constants->size; i<other->constants->size; i++){ DaoValue *value = other->constants->items.pConst[i]->value; DaoRoutine *rout = & value->xRoutine; if( value->type == DAO_ROUTINE && rout->overloads == NULL && rout->routHost == other->objType ){ DString *name = rout->routName; rout = DaoRoutine_Copy( rout, 1, 1 ); value = (DaoValue*) rout; k = DaoRoutine_Finalize( rout, self->objType, deftypes ); #if 0 printf( "%i %p: %s %s\n", i, rout, rout->routName->mbs, rout->routType->name->mbs ); #endif if( rout->attribs & DAO_ROUT_INITOR ){ DRoutines_Add( self->classRoutines->overloads, rout ); }else if( (it = DMap_Find( other->lookupTable, name )) ){ st = LOOKUP_ST( it->value.pInt ); up = LOOKUP_UP( it->value.pInt ); id = LOOKUP_ID( it->value.pInt ); if( st == DAO_CLASS_CONSTANT && up ==0 && id < i ){ DaoValue *v = self->constants->items.pConst[id]->value; if( v->type == DAO_ROUTINE && v->xRoutine.overloads ) DRoutines_Add( v->xRoutine.overloads, rout ); } } DArray_Append( self->constants, DaoConstant_New( value ) ); DArray_Append( routines, rout ); if( k == 0 ) goto Failed; continue; }else if( value->type == DAO_ROUTINE ){ /* No need to added the overloaded routines now; */ /* Each of them has an entry in constants, and will be handled later: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, NULL ); DArray_Append( self->constants, DaoConstant_New( (DaoValue*) routs ) ); continue; } DArray_Append( self->constants, DaoConstant_New( value ) ); DaoValue_Update( & self->constants->items.pConst[i]->value, ns, deftypes ); } for(i=0; i<routines->size; i++){ if( DaoRoutine_DoTypeInference( routines->items.pRoutine[i], 0 ) == 0 ) goto Failed; } DArray_Delete( offsets ); DArray_Delete( routines ); DaoRoutine_Finalize( self->classRoutine, self->objType, deftypes ); return DaoRoutine_DoTypeInference( self->classRoutine, 0 ); Failed: DArray_Delete( offsets ); DArray_Delete( routines ); return 0; }