Beispiel #1
0
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;
}
Beispiel #2
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;
}
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
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" );
	}
}
Beispiel #6
0
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 );
}
Beispiel #8
0
/* 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;
}
Beispiel #9
0
/*
// 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;
}
Beispiel #10
0
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 );
}
Beispiel #11
0
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 );
}
Beispiel #12
0
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;
}