void DaoClass_SetName( DaoClass *self, DString *name, DaoNamespace *ns ) { DaoRoutine *rout; DString *str; if( self->classRoutine ) return; self->inter = DaoInterface_New( ns, name->mbs ); DString_SetMBS( self->inter->abtype->name, "interface<" ); DString_Append( self->inter->abtype->name, name ); DString_AppendChar( self->inter->abtype->name, '>' ); DaoClass_AddReference( self, self->inter ); self->objType = DaoType_New( name->mbs, DAO_OBJECT, (DaoValue*)self, NULL ); self->clsType = DaoType_New( name->mbs, DAO_CLASS, (DaoValue*) self, NULL ); GC_IncRC( self->clsType ); DString_InsertMBS( self->clsType->name, "class<", 0, 0, 0 ); DString_AppendChar( self->clsType->name, '>' ); str = DString_New(1); DString_SetMBS( str, "self" ); DaoClass_AddObjectVar( self, str, NULL, self->objType, DAO_DATA_PRIVATE ); DString_Assign( self->className, name ); DaoClass_AddType( self, name, self->objType ); rout = DaoRoutine_New( ns, self->objType, 1 ); DString_Assign( rout->routName, name ); DString_AppendMBS( rout->routName, "::" ); DString_Append( rout->routName, name ); self->classRoutine = rout; /* XXX class<name> */ GC_IncRC( rout ); rout->routType = DaoType_New( "routine<=>", DAO_ROUTINE, (DaoValue*)self->objType, NULL ); DString_Append( rout->routType->name, name ); DString_AppendMBS( rout->routType->name, ">" ); GC_IncRC( rout->routType ); rout->attribs |= DAO_ROUT_INITOR; DaoClass_AddConst( self, name, (DaoValue*) self, DAO_DATA_PUBLIC ); self->classRoutines = DaoRoutines_New( ns, self->objType, NULL ); DString_Assign( self->classRoutines->routName, name ); DaoClass_AddConst( self, rout->routName, (DaoValue*)self->classRoutines, DAO_DATA_PUBLIC ); self->objType->value = (DaoValue*) DaoObject_Allocate( self, 0 ); self->objType->value->xObject.trait |= DAO_VALUE_CONST|DAO_VALUE_NOCOPY; self->objType->value->xObject.isDefault = 1; GC_IncRC( self->objType->value ); DString_SetMBS( str, "default" ); DaoClass_AddConst( self, str, self->objType->value, DAO_DATA_PUBLIC ); DString_Delete( str ); }
static void DaoClass_SetupMethodFields( DaoClass *self, DaoMethodFields *mf ) { DaoValue *cst; DMap *overloads = DMap_New(D_STRING,0); DNode *it, *search; daoint i, id, pm, pm2; for(i=0; i<mf->names->size; ++i){ DString *name = mf->names->items.pString[i]; it = DMap_Find( self->lookupTable, name ); if( it == NULL ) continue; if( LOOKUP_ST( it->value.pInt ) != DAO_CLASS_CONSTANT ) continue; id = LOOKUP_ID( it->value.pInt ); DMap_Insert( overloads, name, self->constants->items.pConst[id]->value ); } for(i=0; i<mf->names->size; ++i){ DString *name = mf->names->items.pString[i]; it = DMap_Find( self->lookupTable, name ); if( it == NULL ) continue; if( LOOKUP_ST( it->value.pInt ) != DAO_CLASS_CONSTANT ) continue; cst = mf->routines->items.pValue[i]; search = DMap_Find( overloads, name ); if( cst == search->value.pValue ) continue; pm = LOOKUP_PM( it->value.pInt ); pm2 = mf->perms->items.pInt[i]; if( pm2 > pm ) pm = pm2; /* // Add again the overloaded methods, so that a new overloading structure // will be created for the host class. This is necessary to avoid messing // the function calls in the methods of the mixins. */ DaoClass_AddConst( self, name, cst, pm ); } DMap_Delete( overloads ); }
/* 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; }
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 ); }
/* assumed to be called before parsing class body */ void DaoClass_DeriveClassData( DaoClass *self ) { DaoType *type; DaoValue *value; DArray *parents, *offsets; DString *mbs; DNode *it, *search; daoint i, k, id, perm, index; mbs = DString_New(1); 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 ); for(i=0; i<self->superClass->size; i++){ if( self->superClass->items.pValue[i]->type == DAO_CLASS ){ DaoValue *klass = self->superClass->items.pValue[i]; DArray_Append( self->clsType->bases, klass->xClass.clsType ); DArray_Append( self->objType->bases, klass->xClass.objType ); DString_Assign( mbs, klass->xClass.className ); DString_AppendChar( mbs, '#' ); DString_AppendInteger( mbs, i+1 ); DaoClass_AddConst( self, mbs, klass, DAO_DATA_PRIVATE ); }else if( self->superClass->items.pValue[i]->type == DAO_CTYPE ){ DaoCtype *cdata = (DaoCtype*) self->superClass->items.pValue[i]; DaoTypeKernel *kernel = cdata->ctype->kernel; DMap *values = kernel->values; DMap *methods = kernel->methods; DArray_Append( self->clsType->bases, cdata->ctype ); DArray_Append( self->objType->bases, cdata->cdtype ); if( values == NULL ){ DaoNamespace_SetupValues( kernel->nspace, kernel->typer ); values = kernel->values; } if( methods == NULL ){ DaoNamespace_SetupMethods( kernel->nspace, kernel->typer ); methods = kernel->methods; } DString_Assign( mbs, cdata->ctype->name ); // XXX DaoClass_AddConst( self, mbs, (DaoValue*)cdata, DAO_DATA_PRIVATE ); DString_AppendChar( mbs, '#' ); DString_AppendInteger( mbs, i+1 ); DaoClass_AddConst( self, mbs, (DaoValue*)cdata, DAO_DATA_PRIVATE ); } } parents = DArray_New(0); offsets = DArray_New(0); DaoClass_Parents( self, parents, offsets ); for(i=1; i<parents->size; i++){ DaoClass *klass = parents->items.pClass[i]; DaoCdata *cdata = parents->items.pCdata[i]; if( klass->type == DAO_CLASS ){ if( klass->vtable ){ if( self->vtable == NULL ) self->vtable = DHash_New(0,0); for(it=DMap_First(klass->vtable); it; it=DMap_Next(klass->vtable,it)){ DMap_Insert( self->vtable, it->key.pVoid, it->value.pVoid ); } } /* For class data: */ for( id=0; id<klass->cstDataName->size; id++ ){ DString *name = klass->cstDataName->items.pString[id]; value = klass->constants->items.pConst[ id ]->value; search = MAP_Find( klass->lookupTable, name ); if( search == NULL ) continue; perm = LOOKUP_PM( search->value.pInt ); /* NO deriving private member: */ if( perm <= DAO_DATA_PRIVATE ) continue; if( value->type == DAO_ROUTINE ){ if( DString_EQ( value->xRoutine.routName, klass->className ) ) continue; } search = MAP_Find( self->lookupTable, name ); if( search == NULL && value->type == DAO_ROUTINE && value->xRoutine.overloads ){ /* To skip the private methods: */ DaoClass_AddConst( self, name, (DaoValue*)value, perm ); }else if( search == NULL ){ index = LOOKUP_BIND( DAO_CLASS_CONSTANT, perm, i+1, self->constants->size ); MAP_Insert( self->lookupTable, name, index ); DArray_Append( self->constants, klass->constants->items.pConst[id] ); DArray_Append( self->cstDataName, (void*)name ); if( value->type == DAO_ROUTINE && (value->xRoutine.attribs & DAO_ROUT_VIRTUAL) ){ if( self->vtable == NULL ) self->vtable = DHash_New(0,0); MAP_Insert( self->vtable, value, value ); } }else if( value->type == DAO_ROUTINE && value->xRoutine.overloads ){ DRoutines *routs = value->xRoutine.overloads; for(k=0; k<routs->routines->size; k++){ DaoRoutine *rout = routs->routines->items.pRoutine[k]; /* skip methods not defined in this parent type */ if( rout->routHost != klass->objType ) continue; if( rout->attribs & DAO_ROUT_PRIVATE ) continue; DaoClass_AddConst( self, name, (DaoValue*)rout, perm ); } }else if( value->type == DAO_ROUTINE ){ /* skip methods not defined in this parent type */ if( value->xRoutine.routHost != klass->objType ) continue; if( value->xRoutine.attribs & DAO_ROUT_PRIVATE ) continue; DaoClass_AddConst( self, name, value, perm ); } } /* class global data */ for( id=0; id<klass->glbDataName->size; id ++ ){ DString *name = klass->glbDataName->items.pString[id]; DaoVariable *var = klass->variables->items.pVar[id]; search = MAP_Find( klass->lookupTable, name ); perm = LOOKUP_PM( search->value.pInt ); /* NO deriving private member: */ if( perm <= DAO_DATA_PRIVATE ) continue; search = MAP_Find( self->lookupTable, name ); /* To overide data: */ if( search == NULL ){ index = LOOKUP_BIND( DAO_CLASS_VARIABLE, perm, i+1, self->variables->size ); MAP_Insert( self->lookupTable, name, index ); DArray_Append( self->variables, var ); DArray_Append( self->glbDataName, (void*)name ); } } }else if( cdata->type == DAO_CTYPE ){ DaoCtype *ctypeobj = (DaoCtype*) cdata; DaoTypeKernel *kernel = cdata->ctype->kernel; DaoTypeBase *typer = kernel->typer; DMap *values = kernel->values; DMap *methods = kernel->methods; DNode *it; int j; DaoCdataType_SpecializeMethods( cdata->ctype ); kernel = cdata->ctype->kernel; 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 && DMap_Find( self->lookupTable, & name ) == NULL ) DaoClass_AddConst( self, it->key.pString, it->value.pValue, DAO_DATA_PUBLIC ); } } for(it=DMap_First( methods ); it; it=DMap_Next( methods, it )){ DaoRoutine *func = it->value.pRoutine; DaoRoutine **funcs = & func; int k, count = 1; if( it->value.pValue->type == DAO_ROUTINE && it->value.pRoutine->overloads ){ DRoutines *routs = it->value.pRoutine->overloads; funcs = routs->routines->items.pRoutine; count = routs->routines->size; } for(k=0; k<count; k++){ DaoRoutine *func = funcs[k]; if( func->routHost != ctypeobj->cdtype ) continue; if( func->attribs & DAO_ROUT_INITOR ) continue; DaoClass_AddConst( self, it->key.pString, (DaoValue*)func, DAO_DATA_PUBLIC ); } } } } DArray_Delete( parents ); DArray_Delete( offsets ); DString_Delete( mbs ); }