/*
// Note: reference count is not handled for "self"!
// But it is cached in the DaoProcess object, so no need to handle it by user!
*/
int DaoValue_Deserialize( DaoValue **self, DString *serial, DaoNamespace *ns, DaoProcess *proc )
{
	DaoParser *parser = DaoParser_New();
	DArray *types = DArray_New(0);
	DMap *omap = DMap_New(0,0);
	int rc;

	*self = NULL;
	parser->nameSpace = ns;
	parser->vmSpace = ns->vmSpace;
	DaoParser_LexCode( parser, DString_GetMBS( serial ), 0 );
	if( parser->tokens->size == 0 ) goto Failed;

	DArray_PushFront( types, NULL );
	rc = DaoParser_Deserialize( parser, 0, parser->tokens->size-1, self, types, ns, proc, omap );
	if( *self ) DaoProcess_CacheValue( proc, *self );
	DaoParser_Delete( parser );
	DArray_Delete( types );
	DMap_Delete( omap );
	return rc;
Failed:
	DaoParser_Delete( parser );
	DArray_Delete( types );
	DMap_Delete( omap );
	return 0;
}
Exemple #2
0
int DaoCass_DeriveMixinData( DaoClass *self )
{
	DMap *mixed = DMap_New(0,D_MAP);
	DaoMethodFields *mf = DaoMethodFields_New();
	DNode *it, *search;
	daoint i, bl = 1;

	self->cstMixinStart = self->constants->size;
	self->glbMixinStart = self->variables->size;
	self->objMixinStart = self->instvars->size;

	for(i=0; i<self->mixinBases->size; ++i){
		DaoClass *mixin = self->mixinBases->items.pClass[i];
		bl &= DaoClass_MixIn( self, mixin, mixed, mf );
	}
	self->cstMixinEnd = self->constants->size;
	self->glbMixinEnd = self->variables->size;
	self->objMixinEnd = self->instvars->size;

	DaoClass_SetupMethodFields( self, mf );

	self->cstMixinEnd2 = self->constants->size;
	self->glbMixinEnd2 = self->variables->size;
	self->objMixinEnd2 = self->instvars->size;

	DMap_Delete( mixed );
	DaoMethodFields_Delete( mf );
	return bl;
}
Exemple #3
0
static DaoCallServer* DaoCallServer_New( DaoVmSpace *vms )
{
	DaoComplex com = {DAO_COMPLEX,0,0,0,1,{0.0,0.0}};
	DaoCallServer *self = (DaoCallServer*)dao_malloc( sizeof(DaoCallServer) );
	DMutex_Init( & self->mutex );
	DCondVar_Init( & self->condv );
	DCondVar_Init( & self->condv2 );
	DThread_Init( & self->timer );
	self->finishing = 0;
	self->timing = 0;
	self->total = 0;
	self->idle = 0;
	self->stopped = 0;
	self->threads = DArray_New(0);
	self->functions = DArray_New(0);
	self->parameters = DArray_New(0);
	self->events = DArray_New(0);
	self->events2 = DArray_New(0);
	self->waitings = DMap_New(D_VALUE,0);
	self->pending = DHash_New(0,0);
	self->active = DHash_New(0,0);
	self->caches = DArray_New(0);
	self->vmspace = vms;
	self->timestamp = com;
	return self;
}
Exemple #4
0
DaoClass* DaoClass_New()
{
	DaoClass *self = (DaoClass*) dao_calloc( 1, sizeof(DaoClass) );
	DaoValue_Init( self, DAO_CLASS );
	self->trait |= DAO_VALUE_DELAYGC;
	self->className = DString_New(1);

	self->lookupTable = DHash_New(D_STRING,0);
	self->ovldRoutMap = DHash_New(D_STRING,0);
	self->abstypes    = DMap_New(D_STRING,D_VALUE);
	self->constants   = DArray_New(D_VALUE);
	self->variables   = DArray_New(D_VALUE);
	self->instvars    = DArray_New(D_VALUE);
	self->objDataName = DArray_New(D_STRING);
	self->cstDataName = DArray_New(D_STRING);
	self->glbDataName = DArray_New(D_STRING);
	self->parent = NULL;
	self->mixinBases = DArray_New(0);  /* refcount handled in ::allBases; */
	self->allBases   = DArray_New(D_VALUE);
	self->mixins  = DArray_New(0);
	self->ranges  = DVector_New(sizeof(ushort_t));
	self->offsets = DVector_New(sizeof(ushort_t));
	self->references  = DArray_New(D_VALUE);
	self->inter = NULL;

	self->cstMixinStart = self->cstMixinEnd = self->cstMixinEnd2 = 0;
	self->glbMixinStart = self->glbMixinEnd = self->glbMixinEnd2 = 0;
	self->objMixinStart = self->objMixinEnd = self->objMixinEnd2 = 0;
	self->cstParentStart = self->cstParentEnd = 0;
	self->glbParentStart = self->glbParentEnd = 0;
	return self;
}
Exemple #5
0
static void DMap_SortMethods( DMap *hash, DList *methods )
{
	DMap *map = DMap_New( DAO_DATA_STRING, 0 );
	DString *name = DString_New();
	DNode *it;
	daoint i, n;
	for(it=DMap_First(hash); it; it=DMap_Next(hash,it)){
		if( it->value.pRoutine->overloads ){
			DRoutines *one = it->value.pRoutine->overloads;
			for(i=0,n=one->routines->size; i<n; i++){
				DaoRoutine *rout = one->routines->items.pRoutine[i];
				DString_Assign( name, rout->routName );
				DString_AppendChars( name, " " );
				DString_Append( name, rout->routType->name );
				DMap_Insert( map, name, (void*)rout );
			}
		}else{
			DaoRoutine *rout = it->value.pRoutine;
			DString_Assign( name, rout->routName );
			DString_AppendChars( name, " " );
			DString_Append( name, rout->routType->name );
			DMap_Insert( map, name, (void*)rout );
		}
	}
	DList_Clear( methods );
	for(it=DMap_First(map); it; it=DMap_Next(map,it))
		DList_Append( methods, it->value.pVoid );
	DMap_Delete( map );
	DString_Delete( name );
}
Exemple #6
0
static DaoCallServer* DaoCallServer_New( DaoVmSpace *vms )
{
	DaoCallServer *self = (DaoCallServer*)dao_malloc( sizeof(DaoCallServer) );
	DMutex_Init( & self->mutex );
	DCondVar_Init( & self->condv );
	DCondVar_Init( & self->condv2 );
	DThread_Init( & self->timer );
	self->finishing = 0;
	self->timing = 0;
	self->total = 0;
	self->vacant = 0;
	self->idle = 0;
	self->stopped = 0;
	self->threads = DList_New(0);
	self->functions = DList_New(0);
	self->parameters = DList_New(0);
	self->owners = DList_New(0);
	self->events = DList_New(0);
	self->events2 = DList_New(0);
	self->waitings = DMap_New( DAO_DATA_COMPLEX, 0 );
	self->pending = DHash_New(0,0);
	self->active = DHash_New(0,0);
	self->caches = DList_New(0);
	self->vmspace = vms;
	self->timestamp.real = 0.0;
	self->timestamp.imag = 0.0;
	return self;
}
Exemple #7
0
DaoxFont* DaoxFont_New()
{
	DaoxFont *self = (DaoxFont*) dao_calloc( 1, sizeof(DaoxFont) );
	DaoCstruct_Init( (DaoCstruct*)self, daox_type_font );
	self->buffer = DString_New();
	self->glyphs = DMap_New(0,DAO_DATA_VALUE);
	return self;
}
Exemple #8
0
static void DaoIO_Write0( DaoStream *self, DaoProcess *proc, DaoValue *p[], int N )
{
	DMap *cycData;
	int i;
	if( (self->attribs & (DAO_IO_FILE | DAO_IO_PIPE)) && self->file == NULL ){
		DaoProcess_RaiseException( proc, DAO_ERROR, "stream is not open!" );
		return;
	}
	cycData = DMap_New(0,0);
	for(i=0; i<N; i++) DaoValue_Print( p[i], proc, self, cycData );
	DMap_Delete( cycData );
}
Exemple #9
0
void DaoValue_Print( DaoValue *self, DaoProcess *proc, DaoStream *stream, DMap *cycData )
{
	DString *name;
	DaoTypeBase *typer;
	DMap *cd = cycData;
	if( self == NULL ){
		DaoStream_WriteMBS( stream, "none[0x0]" );
		return;
	}
	if( cycData == NULL ) cycData = DMap_New(0,0);
	switch( self->type ){
	case DAO_INTEGER :
		DaoStream_WriteInt( stream, self->xInteger.value ); break;
	case DAO_FLOAT   :
		DaoStream_WriteFloat( stream, self->xFloat.value ); break;
	case DAO_DOUBLE  :
		DaoStream_WriteFloat( stream, self->xDouble.value ); break;
	case DAO_COMPLEX :
		DaoStream_WriteFloat( stream, self->xComplex.value.real );
		if( self->xComplex.value.imag >= -0.0 ) DaoStream_WriteMBS( stream, "+" );
		DaoStream_WriteFloat( stream, self->xComplex.value.imag );
		DaoStream_WriteMBS( stream, "C" );
		break;
#ifdef DAO_WITH_LONGINT
	case DAO_LONG :
		name = DString_New(1);
		DLong_Print( self->xLong.value, name );
		DaoStream_WriteString( stream, name );
		DString_Delete( name );
		break;
#endif
	case DAO_ENUM  :
		name = DString_New(1);
		DaoEnum_MakeName( & self->xEnum, name );
		DaoStream_WriteMBS( stream, name->mbs );
		DaoStream_WriteMBS( stream, "(" );
		DaoStream_WriteInt( stream, self->xEnum.value );
		DaoStream_WriteMBS( stream, ")" );
		DString_Delete( name );
		break;
	case DAO_STRING  :
		DaoStream_WriteString( stream, self->xString.data ); break;
	default :
		typer = DaoVmSpace_GetTyper( self->type );
		if( typer->core->Print == DaoValue_Print ){
			DaoValue_BasicPrint( self, proc, stream, cycData );
			break;
		}
		typer->core->Print( self, proc, stream, cycData );
		break;
	}
	if( cycData != cd ) DMap_Delete( cycData );
}
int DaoValue_Serialize( DaoValue *self, DString *serial, DaoNamespace *ns, DaoProcess *proc )
{
	DaoType *type = DaoNamespace_GetType( ns, self );
	DString *buf = DString_New(1);
	DMap *omap = DMap_New(0,0);
	int rc;
	DString_Clear( serial );
	DString_ToMBS( serial );
	rc = DaoValue_Serialize2( self, serial, ns, proc, type, buf, omap );
	DString_Delete( buf );
	DMap_Delete( omap );
	return rc;
}
Exemple #11
0
DaoClass* DaoClass_New()
{
	DaoClass *self = (DaoClass*) dao_calloc( 1, sizeof(DaoClass) );
	DaoValue_Init( self, DAO_CLASS );
	self->trait |= DAO_VALUE_DELAYGC;
	self->className = DString_New(1);

	self->lookupTable = DHash_New(D_STRING,0);
	self->ovldRoutMap = DHash_New(D_STRING,0);
	self->abstypes    = DMap_New(D_STRING,D_VALUE);
	self->constants   = DArray_New(D_VALUE);
	self->variables   = DArray_New(D_VALUE);
	self->instvars    = DArray_New(D_VALUE);
	self->objDataName = DArray_New(D_STRING);
	self->cstDataName = DArray_New(D_STRING);
	self->glbDataName = DArray_New(D_STRING);
	self->superClass  = DArray_New(D_VALUE);
	self->references  = DArray_New(D_VALUE);
	return self;
}
Exemple #12
0
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 );
}
Exemple #13
0
int DaoParser_ParseMacro( DaoParser *self, int start )
{
	int rb1, rb2, i = start, N = self->tokens->size;
	DaoToken **toks = self->tokens->items.pToken;
	DMacroUnit *first;
	DaoMacro *macro;
	DString *lang = NULL;
	DArray  *stops;
	DMap  *markers;
	DNode *it;

	if( start + 5 >= N ) return -1;
	if( toks[start+1]->type != DTOK_LCB ){
		lang = & toks[start+1]->string;
		if( toks[start+1]->type != DTOK_IDENTIFIER ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		if( lang->size == 3 && strcmp( lang->mbs, "dao" ) == 0 ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		start += 1;
	}
	if( toks[start+1]->name != DTOK_LCB ) return -1;

	self->curLine = toks[start]->line;
	rb1 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, -1 );
	if( rb1 <0 || rb1 +3 >= N ) return -1;
	if( toks[rb1+1]->name != DKEY_AS || toks[rb1+2]->name != DTOK_LCB ){
		DaoParser_Error( self, DAO_CTW_INV_MAC_DEFINE, NULL );
		return -1;
	}
	rb2 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, rb1 + 1, -1 );
	if( rb2 <0 ) return -1;

	/*
	   for( i=start; i<rb2; i++ ) printf( "%s  ", toks[i]->string.mbs ); printf("\n");
	 */

	macro = DaoMacro_New();
	markers = DMap_New(D_STRING,0);

	if( DaoParser_MakeMacroGroup( self, macro->macroMatch, macro->macroMatch, start+2, rb1, markers, NULL ) ==0 ){
		goto Error;
	}
	if( macro->macroMatch->units->size == 0 ) goto Error;
	first = (DMacroUnit*) macro->macroMatch->units->items.pVoid[0];
	if( first->type != DMACRO_TOK ){
		DaoParser_Error( self, DAO_CTW_INV_MAC_FIRSTOK, & toks[i]->string );
		goto Error;
	}
	for(it=DMap_First(markers); it; it=DMap_Next(markers,it)){
		if( it->value.pInt > 1 ){
			DaoParser_Error( self, DAO_CTW_REDEF_MAC_MARKER, it->key.pString );
			goto Error;
		}
	}

	DMap_Clear( markers );
	if( toks[rb1+3]->line != toks[rb1+2]->line ) macro->macroApply->cpos = toks[rb1+3]->cpos;
	if( DaoParser_MakeMacroGroup( self, macro->macroApply, macro->macroApply, rb1+3, rb2, NULL, markers ) ==0 ){
		goto Error;
	}
	for(it=DMap_First(markers); it; it=DMap_Next(markers,it)){
		DArray_Append( macro->keyListApply, it->key.pString );
	}

	stops = DArray_New(D_TOKEN);
	DMacroGroup_SetStop( macro->macroMatch, stops );
	DMacroGroup_FindVariables( macro->macroMatch );
	DArray_Clear( stops );
	DMacroGroup_SetStop( macro->macroApply, stops );
	DaoNamespace_AddMacro( self->nameSpace, lang, & first->marker->string, macro );
	DArray_Delete( stops );
	DMap_Delete( markers );
	return rb2;
Error:
	DaoMacro_Delete( macro );
	DMap_Delete( markers );
	return -1;
}
Exemple #14
0
void DaoProfiler_Report( DaoProfiler *self0, DaoStream *stream )
{
	DaoComplex com = {DAO_COMPLEX,0,0,0,1,{0.0,0.0}};
	DaoxProfiler *self = (DaoxProfiler*) self0;
	DMap *summary = DMap_New( DAO_DATA_VALUE, 0 );
	DMap *summary2 = DMap_New( DAO_DATA_VALUE, 0 );
	DString *name1 = DString_New();
	DString *name2 = DString_New();
	DNode *it, *it2;
	int count, max = 20;
	char buf1[32];
	char buf2[24];
	char buf[120];

	for(it=DMap_First(self->profile); it; it=DMap_Next(self->profile,it)){
		DaoRoutine *callee = (DaoRoutine*) it->key.pValue;
		com.value = DaoProfiler_Sum( it->value.pMap );
		com.value.real = - com.value.real;
		com.value.imag = - com.value.imag;
		DMap_Insert( summary, & com, it );
	}

	DaoStream_WriteChars( stream, "\n" );
	DaoStream_WriteChars( stream, delimiter );
	DaoStream_WriteChars( stream, delimiter2 );
	snprintf( buf, sizeof(buf), header_format, "Routine", "#Calls", "CPU Time" );
	DaoStream_WriteChars( stream, buf );
	DaoStream_WriteChars( stream, delimiter2 );
	for(count=max,it=DMap_First(summary); it; it=DMap_Next(summary,it),--count){
		DNode *it2 = (DNode*) it->value.pVoid;
		dao_complex data = it->key.pValue->xComplex.value;
		DaoRoutine *callee = (DaoRoutine*) it2->key.pValue;
		DaoRoutine_MakeName( callee, name1, 28, 10, 2 );
		snprintf( buf, sizeof(buf), row_format, name1->chars, (int) -data.imag, -data.real );
		DaoStream_WriteChars( stream, buf );
		if( count == 0 ) break;
	}

	DaoStream_WriteChars( stream, "\n" );
	DaoStream_WriteChars( stream, delimiter3 );
	snprintf( buf, sizeof(buf), header_format2, "Routine", "Caller", "#Calls", "CPU Time" );
	DaoStream_WriteChars( stream, buf );
	DaoStream_WriteChars( stream, delimiter3 );
	for(count=max,it=DMap_First(summary); it; it=DMap_Next(summary,it),--count){
		DNode *it2 = (DNode*) it->value.pVoid;
		DaoRoutine *callee = (DaoRoutine*) it2->key.pValue;
		DMap *profile = it2->value.pMap;

		DaoRoutine_MakeName( callee, name1, 30, 0, 0 );

		DMap_Reset( summary2 );
		for(it2=DMap_First(profile); it2; it2=DMap_Next(profile,it2)){
			DaoRoutine *caller = (DaoRoutine*) it2->key.pValue;
			DaoComplex *data = (DaoComplex*) it2->value.pValue;
			com.value.real = - data->value.real;
			com.value.imag = - data->value.imag;
			DMap_Insert( summary2, & com, caller );
		}
		for(it2=DMap_First(summary2); it2; it2=DMap_Next(summary2,it2)){
			DaoRoutine *caller = (DaoRoutine*) it2->value.pValue;
			dao_complex data = it2->key.pValue->xComplex.value;
			DString_Reset( name2, 0 );
			if( caller ) DaoRoutine_MakeName( caller, name2, 22, 0, 0 );
			snprintf( buf, sizeof(buf), row_format2, name1->chars, name2->chars, (int) -data.imag, -data.real );
			DaoStream_WriteChars( stream, buf );
			DString_Reset( name1, 0 );
		}
		if( count == 0 ) break;
	}
	DString_Delete( name1 );
	DString_Delete( name2 );
}
Exemple #15
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;
}
Exemple #16
0
void STD_Debug( DaoProcess *proc, DaoValue *p[], int N )
{
	DaoUserHandler *handler = proc->vmSpace->userHandler;
	DaoRoutine *routine = proc->activeRoutine;
	DaoStream *stream = proc->vmSpace->stdioStream;
	DString *input;
	DArray *tokens;
	DMap   *cycData;
	char *chs, *cmd;
	int i;
	if( ! (proc->vmSpace->options & DAO_OPTION_DEBUG ) ) return;
	input = DString_New(1);
	if( N > 0 && DaoValue_CastCstruct( p[0], dao_type_stream ) ){
		stream = (DaoStream*)p[0];
		p ++;
		N --;
	}
	if( N > 0 ){
		Dao_AboutVars( proc->activeNamespace, p, N, input );
		DaoStream_WriteString( stream, input );
		DaoStream_WriteMBS( stream, "\n" );
		DString_Delete( input );
		return;
	}
	if( handler && handler->StdlibDebug ){
		handler->StdlibDebug( handler, proc );
		return;
	}
	tokens = DArray_New(D_STRING);
	cycData = DMap_New(0,0);
	while(1){
		if( proc->vmSpace->ReadLine ){
			chs = proc->vmSpace->ReadLine( "(debug) " );
			if( chs ){
				DString_SetMBS( input, chs );
				DString_Trim( input );
				if( input->size && proc->vmSpace->AddHistory )
					proc->vmSpace->AddHistory( chs );
				dao_free( chs );
			}
		}else{
			DaoStream_WriteMBS( stream, "(debug) " );
			DaoStream_ReadLine( stream, input );
		}
		if( input->size == 0 ) continue;
		SplitByWhiteSpaces( input->mbs, tokens );
		if( tokens->size == 0 ) continue;
		cmd = tokens->items.pString[0]->mbs;
		if( strcmp( cmd, "q" ) == 0 || strcmp( cmd, "quit" ) == 0 ){
			break;
		}else if( strcmp( cmd, "k" ) == 0 || strcmp( cmd, "kill" ) == 0 ){
			proc->status = DAO_PROCESS_ABORTED;
			break;
		}else if( strcmp( cmd, "a" ) == 0 || strcmp( cmd, "about" ) == 0 ){
			if( tokens->size > 1 ){
				ushort_t reg = (ushort_t)strtod( tokens->items.pString[1]->mbs, 0 );
				DaoType *tp = proc->activeTypes[ reg ];
				DString_Clear( input );
				Dao_AboutVar( proc->activeNamespace, proc->activeValues[reg], input );
				DaoStream_WriteMBS( stream, "type: " );
				if( tp )
					DaoStream_WriteString( stream, tp->name );
				else
					DaoStream_WriteMBS( stream, "?" );
				DaoStream_WriteMBS( stream, ", value: " );
				DaoStream_WriteString( stream, input );
				DaoStream_WriteMBS( stream, "\n" );
			}
		}else if( strcmp( cmd, "g" ) == 0 || strcmp( cmd, "goto" ) == 0 ){
			if( tokens->size > 1 ){
				int n = atoi( tokens->items.pString[1]->mbs );
				int entry = proc->activeCode - proc->activeRoutine->body->vmCodes->data.codes;
				if( n < 0 ) n = entry - n;
				if( n >= routine->body->vmCodes->size ) n = routine->body->vmCodes->size -1;
				proc->topFrame->entry = n;
				proc->status = DAO_PROCESS_STACKED;
				return;
			}
		}else if( strcmp( cmd, "h" ) == 0 || strcmp( cmd, "help" ) == 0 ){
			DaoStream_WriteMBS( stream, help );
		}else if( strcmp( cmd, "l" ) == 0 || strcmp( cmd, "list" ) == 0 ){
			DString *mbs = DString_New(1);
			int entry = proc->activeCode - proc->activeRoutine->body->vmCodes->data.codes;
			int start = entry - 10;
			int end = entry;
			if( tokens->size >1 ){
				int dn = atoi( tokens->items.pString[1]->mbs );
				if( dn < 0 ){
					start = entry + dn;
				}else if( dn > 0 ){
					start = entry;
					end = entry + dn;
				}
			}
			if( start < 0 ) start = 0;
			if( end >= routine->body->vmCodes->size ) end = routine->body->vmCodes->size - 1;
			DaoStream_WriteString( stream, routine->routName );
			DaoStream_WriteMBS( stream, "(): " );
			if( routine->routType ) DaoStream_WriteString( stream, routine->routType->name );
			DaoStream_WriteMBS( stream, "\n" );
			DaoStream_WriteMBS( stream, daoRoutineCodeHeader );
			DaoStream_WriteMBS( stream, sep );
			for( i=start; i<=end; i++ ){
				DaoRoutine_FormatCode( routine, i, *routine->body->annotCodes->items.pVmc[i], mbs );
				DaoStream_WriteString( stream, mbs );
			}
			DString_Delete( mbs );
		}else if( strcmp( cmd, "p" ) == 0 || strcmp( cmd, "print" ) == 0 ){
			if( tokens->size > 1 ){
				ushort_t reg = (ushort_t)atoi( tokens->items.pString[1]->mbs );
				DaoValue_Print( proc->activeValues[reg], proc, stream, cycData );
				DaoStream_WriteMBS( stream, "\n" );
			}
		}else if( strcmp( cmd, "t" ) == 0 || strcmp( cmd, "trace" ) == 0 ){
			int depth = 1;
			if( tokens->size >1 ) depth = atoi( tokens->items.pString[1]->mbs );
			DaoProcess_Trace( proc, depth );
		}else{
			DaoStream_WriteMBS( stream, "Unknown debugging command.\n" );
		}
	}
	DString_Delete( input );
	DArray_Delete( tokens );
}
void DaoNamespace_Restore( DaoNamespace *self, DaoProcess *proc, FILE *fin )
{
	DaoParser *parser = DaoParser_New();
	DString *line = DString_New(1);
	DArray *types = DArray_New(0);
	DArray *tokens = parser->tokens;
	DMap *omap = DMap_New(0,0);
	DString *name;
	DNode *node;

	parser->nameSpace = self;
	parser->vmSpace = self->vmSpace;
	while( DaoFile_ReadLine( fin, line ) ){
		DaoValue *value = NULL;
		int st = DAO_GLOBAL_VARIABLE;
		int pm = DAO_DATA_PRIVATE;
		int i, n, start = 0;
		char *mbs;

		DaoParser_LexCode( parser, line->mbs, 0 );
		if( tokens->size == 0 ) continue;
		name = & tokens->items.pToken[start]->string;
		if( name->size == 6 && strcmp( name->mbs, "inputs" ) == 0 ){
			if( tokens->size < 3 ) continue;
			DString_Clear( line );
			n = tokens->items.pToken[start+2]->string.size;
			mbs = tokens->items.pToken[start+2]->string.mbs;
			for(i=0; i<n; i++){
				char c1 = mbs[i];
				char c2 = mbs[i+1];
				if( c1 < 'A' || c1 > 'P' ) continue;
				DString_AppendChar( line, (char)((c1-'A')*16 + (c2-'A')) );
				i += 1;
			}
			/* printf( "%s\n", line->mbs ); */
			DaoProcess_Eval( proc, self, line->mbs );
			continue;
		}
		switch( tokens->items.pToken[start]->name ){
		case DKEY_PRIVATE   : pm = DAO_DATA_PRIVATE;   start += 1; break;
		case DKEY_PROTECTED : pm = DAO_DATA_PROTECTED; start += 1; break;
		case DKEY_PUBLIC    : pm = DAO_DATA_PUBLIC;    start += 1; break;
		}
		if( start >= tokens->size ) continue;
		switch( tokens->items.pToken[start]->name ){
		case DKEY_CONST : st = DAO_GLOBAL_CONSTANT; start += 1; break;
		case DKEY_VAR   : st = DAO_GLOBAL_VARIABLE; start += 1; break;
		}
		if( tokens->items.pToken[start]->name != DTOK_IDENTIFIER ) continue;
		name = & tokens->items.pToken[start]->string;
		start += 1;
		if( start + 3 >= tokens->size ) continue;
		if( tokens->items.pToken[start]->name != DTOK_ASSN ) continue;
		start += 1;

		DArray_Clear( parser->errors );
		DArray_Clear( types );
		DArray_PushFront( types, NULL );
		DaoParser_Deserialize( parser, start, tokens->size-1, &value, types, self, proc, omap );
		if( value == NULL ) continue;
		node = DMap_Find( self->lookupTable, name );
		if( node ) continue;
		if( st == DAO_GLOBAL_CONSTANT ){
			DaoNamespace_AddConst( self, name, value, pm );
		}else{
			DaoNamespace_AddVariable( self, name, value, NULL, pm );
		}
	}
	DMap_Delete( omap );
	DString_Delete( line );
	DArray_Delete( types );
	DaoParser_Delete( parser );
}
Exemple #18
0
int DaoParser_MacroTransform( DaoParser *self, DaoMacro *macro, int start, int tag )
{
	DString *mbs = DString_New(1);
	DArray *toks = DArray_New(D_TOKEN);
	DArray *all = DArray_New(0);
	DMap *tokMap = DMap_New(D_STRING,0);
	DMap *used = DMap_New(0,D_MAP);
	DNode *it;
	daoint i;
	int j, p0, lev = 0, adjust=0;
	int indent[10];
	char buf[20];

	sprintf( buf, " %p %x", self->nameSpace, tag );
	DString_SetMBS( mbs, buf );
	for(i=0; i<10; i++) indent[i] = -1;

	j = DaoParser_MacroMatch( self, start, self->tokens->size, macro->macroMatch, tokMap, lev, all, indent );
	/*
	   printf( "MacroTransform %i\n", j );
	 */
	if( j <0 ) goto Failed;

	for( it = DMap_First( tokMap ); it != NULL; it = DMap_Next( tokMap, it ) ){
		DMacroNode *node = (DMacroNode*) it->value.pVoid;
		while( node->parent ) node = node->parent;
		it->value.pVoid = node;
	}

	lev = 0;
	p0 = self->tokens->items.pToken[start]->line;
	adjust = self->tokens->items.pToken[start]->cpos - macro->macroApply->cpos;
	if( DaoParser_MacroApply( self, toks, macro->macroApply, tokMap, used, lev, mbs, p0, adjust ) <0 )
		goto Failed;

	/*
	   for(i=0; i<toks->size; i++) printf( "%s  ", toks->items.pToken[i]->string.mbs );
	   printf( "\n" );
	 */
	DArray_Erase( self->tokens, start, j-start );
	DArray_InsertArray( self->tokens, start, toks, 0, -1 );
	/*
	   for(i=0; i<toks->size; i++){
	   DArray_Insert( self->tokStr, (void*)toks->items.pString[i], start+i );
	   DArray_Insert( self->tokPos, (void*)poss->items.pInt[i], start+i );
	   }
	 */
	j = toks->size;
	DString_Delete( mbs );
	for(i=0; i<all->size; i++) DMacroNode_Delete( (DMacroNode*) all->items.pVoid[i] );
	DArray_Delete( all );
	DArray_Delete( toks );
	DMap_Delete( tokMap );
	DMap_Delete( used );
	return start + j;
Failed :
	DString_Delete( mbs );
	for(i=0; i<all->size; i++) DMacroNode_Delete( (DMacroNode*) all->items.pVoid[i] );
	DArray_Delete( all );
	DArray_Delete( toks );
	DMap_Delete( tokMap );
	DMap_Delete( used );
	return -1;
}
Exemple #19
0
DaoClass* DaoClass_Instantiate( DaoClass *self, DArray *types )
{
	DaoClass *klass = NULL;
	DaoType *type;
	DString *name;
	DNode *node;
	DMap *deftypes;
	daoint lt = DString_FindChar( self->className, '<', 0 );
	daoint i, holders = 0;
	if( self->typeHolders == NULL || self->typeHolders->size ==0 ) return self;
	while( types->size < self->typeHolders->size ){
		type = self->typeDefaults->items.pType[ types->size ];
		if( type == NULL ) type = self->typeHolders->items.pType[ types->size ];
		DArray_Append( types, type );
	}
	name = DString_New(1);
	DString_Append( name, self->className );
	if( lt != MAXSIZE ) DString_Erase( name, lt, MAXSIZE );
	DString_AppendChar( name, '<' );
	for(i=0; i<types->size; i++){
		type = types->items.pType[i];
		holders += type->tid == DAO_THT;
		if( i ) DString_AppendChar( name, ',' );
		DString_Append( name, type->name );
	}
	DString_AppendChar( name, '>' );
	while( self->templateClass ) self = self->templateClass;
	node = DMap_Find( self->instanceClasses, name );
	if( node ){
		klass = node->value.pClass;
	}else{
		deftypes = DMap_New(0,0);
		klass = DaoClass_New();
		if( holders ) klass->templateClass = self;
		DMap_Insert( self->instanceClasses, name, klass );
		DaoClass_AddReference( self, klass ); /* No need for cleanup of klass; */
		DaoClass_SetName( klass, name, self->classRoutine->nameSpace );
		for(i=0; i<types->size; i++){
			type = types->items.pType[i];
			if( DaoType_MatchTo( type, self->typeHolders->items.pType[i], deftypes ) ==0 ){
				DString_Delete( name );
				return NULL;
			}
			MAP_Insert( deftypes, self->typeHolders->items.pVoid[i], type );
		}
		klass->objType->nested = DArray_New(D_VALUE);
		DArray_Assign( klass->objType->nested, types );
		if( DaoClass_CopyField( klass, self, deftypes ) == 0 ){
			DString_Delete( name );
			return NULL;
		}
		DaoClass_DeriveClassData( klass );
		DaoClass_DeriveObjectData( klass );
		DaoClass_ResetAttributes( klass );
		DMap_Delete( deftypes );
		if( holders ){
			klass->typeHolders = DArray_New(0);
			klass->typeDefaults = DArray_New(0);
			klass->instanceClasses = DMap_New(D_STRING,0);
			DMap_Insert( klass->instanceClasses, klass->className, klass );
			for(i=0; i<types->size; i++){
				DArray_Append( klass->typeHolders, types->items.pType[i] );
				DArray_Append( klass->typeDefaults, NULL );
			}
			for(i=0; i<klass->typeHolders->size; i++){
				DaoClass_AddReference( klass, klass->typeHolders->items.pType[i] );
				DaoClass_AddReference( klass, klass->typeDefaults->items.pType[i] );
			}
		}
	}
	DString_Delete( name );
	return klass;
}
Exemple #20
0
/*
// C printf format: %[parameter][flags][width][.precision][length]type
//
// Dao writef format: %[parameter][flags][width][.precision]type[color]
//
// Where 'parameter', 'flags', 'width' and 'precision' will conform to the
// C format, but 'type' can only be:
//   c, d, i, o, u, x/X : for integer;
//   e/E, f/F, g/G : for float and double;
//   s : for string;
//   p : for any type, write address;
//   a : automatic, for any type, write in the default format;
// Namely the standard ones exception 'n', and plus 'a'.
//
// Optional 'color' format will be in form of: [foreground:background], [foreground]
// or [:background]. The supported color name format will depend on the color printing
// handle. Mininum requirement is the support of the following 8 color names:
// black, white, red, green, blue, yellow, magenta, cyan.
*/
static void DaoIO_Writef0( DaoStream *self, DaoProcess *proc, DaoValue *p[], int N )
{
	DaoValue *value;
	DMap *cycData;
	DString *format, *fmt2;
	DString *fgcolor, *bgcolor;
	const char *convs = "aspcdiouxXfFeEgG";
	char F, *s, *end, *fg, *bg, *fmt, message[100];
	int k, id = 1;
	if( (self->attribs & (DAO_IO_FILE | DAO_IO_PIPE)) && self->file == NULL ){
		DaoProcess_RaiseException( proc, DAO_ERROR, "stream is not open!" );
		return;
	}
	cycData = DMap_New(0,0);
	fmt2 = DString_New(1);
	fgcolor = DString_New(1);
	bgcolor = DString_New(1);
	format = DString_Copy( p[0]->xString.data );
	DString_ToMBS( format );
	s = format->mbs;
	end = s + format->size;
	for(; s<end; s++){
		k = 0;
		if( *s =='%' ){
			fmt = s;
			s += 1;
			if( *s =='%' || *s == '[' ){
				DaoStream_WriteChar( self, *s );
				continue;
			}
			if( isdigit( *s ) && (*s > '0') ){
				while( isdigit( *s ) ) s += 1;
				if( *s == '$' ){ /* parameter: number$ */
					*s = '\0';
					k = strtol( fmt + 1, NULL, 10 );
					if( k == 0 || k >= N ){
						DaoProcess_RaiseException( proc, DAO_WARNING, "invalid parameter number" );
					}
					*s = '%';
					fmt = s ++;
				}
			}
			/* flags: */
			while( *s == '+' || *s == '-' || *s == '#' || *s == '0' || *s == ' ' ) s += 1;
			while( isdigit( *s ) ) s += 1; /* width; */
			if( *s == '.' ){ /* precision: */
				s += 1;
				while( isdigit( *s ) ) s += 1;
			}
			DString_SetDataMBS( fmt2, fmt, s - fmt + 1 );
			if( strchr( convs, *s ) == NULL ){
				DaoProcess_RaiseException( proc, DAO_WARNING, "invalid format conversion" );
				continue;
			}
			F = *s;
			s += 1;
			fg = bg = NULL;
			if( *s == '[' ){
				s += 1;
				fmt = s;
				while( isalnum( *s ) ) s += 1;
				DString_SetDataMBS( fgcolor, fmt, s - fmt );
				if( fgcolor->size ) fg = fgcolor->mbs;
				if( *s == ':' ){
					s += 1;
					fmt = s;
					while( isalnum( *s ) ) s += 1;
					DString_SetDataMBS( bgcolor, fmt, s - fmt );
					if( bgcolor->size ) bg = bgcolor->mbs;
				}
				if( *s != ']' ) DaoProcess_RaiseException( proc, DAO_WARNING, "invalid color format" );
			}else{
				s -= 1;
			}
			if( k == 0 ) k = id;
			value = p[k];
			id += 1;
			if( fg || bg ) DaoStream_SetColor( self, fg, bg );
			self->format = fmt2->mbs;
			if( value == NULL ){
				if( F == 'p' ){
					DaoStream_WriteMBS( self, "0x0" );
				}else{
					DaoProcess_RaiseException( proc, DAO_WARNING, "null parameter" );
				}
			}
			self->format = fmt2->mbs;
			if( F == 'c' || F == 'd' || F == 'i' || F == 'o' || F == 'x' || F == 'X' ){
				if( sizeof(daoint) != 4 ) DString_InsertChar( fmt2, DAO_INT_FORMAT[0], fmt2->size-1 );
				self->format = fmt2->mbs;
				if( value->type == DAO_INTEGER ){
					DaoStream_WriteInt( self, value->xInteger.value );
				}else{
					goto WrongParameter;
				}
			}else if( toupper( F ) == 'E' || toupper( F ) == 'F' || toupper( F ) == 'G' ){
				if( value->type == DAO_FLOAT ){
					DaoStream_WriteFloat( self, value->xFloat.value );
				}else if( value->type == DAO_DOUBLE ){
					DaoStream_WriteFloat( self, value->xDouble.value );
				}else{
					goto WrongParameter;
				}
			}else if( F == 's' && value->type == DAO_STRING ){
				DaoStream_WriteString( self, value->xString.data );
			}else if( F == 'p' ){
				DaoStream_WritePointer( self, value );
			}else if( F == 'a' ){
				self->format = NULL;
				DaoValue_Print( value, proc, self, cycData );
			}else{
				goto WrongParameter;
			}
			self->format = NULL;
			if( fg || bg ) DaoStream_SetColor( self, NULL, NULL );
			continue;
WrongParameter:
			self->format = NULL;
			if( fg || bg ) DaoStream_SetColor( self, NULL, NULL );
			sprintf( message, "%i-th parameter has wrong type for format \"%s\"!", k, fmt2->mbs );
			DaoProcess_RaiseException( proc, DAO_WARNING, message );
		}else{
			DaoStream_WriteChar( self, *s );
		}
	}
	DString_Delete( fgcolor );
	DString_Delete( bgcolor );
	DString_Delete( format );
	DString_Delete( fmt2 );
	DMap_Delete( cycData );
}
Exemple #21
0
int DaoParser_ParseMacro( DaoParser *self, int start )
{
	int rb1, rb2, i = start, N = self->tokens->size;
	DaoToken **toks = self->tokens->items.pToken;
	DaoMacro *macro;
	DString *lang = NULL;
	DArray  *stops;
	DMap  *markers;

	if( start + 5 >= N ) return -1;
	if( toks[start+1]->type != DTOK_LCB ){
		lang = & toks[start+1]->string;
		if( toks[start+1]->type != DTOK_IDENTIFIER ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		if( lang->size == 3 && strcmp( lang->mbs, "dao" ) == 0 ){
			DaoParser_Error( self, DAO_TOKEN_NEED_NAME, lang );
			return -1;
		}
		start += 1;
	}
	if( toks[start+1]->name != DTOK_LCB ) return -1;

	self->curLine = toks[start]->line;
	rb1 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, start, -1 );
	if( rb1 <0 || rb1 +3 >= N ) return -1;
	if( toks[rb1+1]->name != DKEY_AS || toks[rb1+2]->name != DTOK_LCB ){
		DaoParser_Error( self, DAO_CTW_INV_MAC_DEFINE, NULL );
		return -1;
	}
	rb2 = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, rb1 + 1, -1 );
	if( rb2 <0 ) return -1;

	/*
	   for( i=start; i<rb2; i++ ) printf( "%s  ", toks[i]->string.mbs ); printf("\n");
	 */

	macro = DaoMacro_New();

	if( DaoParser_MakeMacroGroup( self, macro->macroMatch, macro->macroMatch, start+2, rb1 ) ==0 ){
		DaoMacro_Delete( macro );
		return -1;
	}
	if( macro->macroMatch->units->size >0 ){
		DMacroUnit *unit = (DMacroUnit*) macro->macroMatch->units->items.pVoid[0];
		if( unit->type != DMACRO_TOK )
			DaoParser_Error( self, DAO_CTW_INV_MAC_FIRSTOK, & toks[i]->string );
	}
	if( toks[rb1+3]->line != toks[rb1+2]->line ) macro->macroApply->cpos = toks[rb1+3]->cpos;
	if( DaoParser_MakeMacroGroup( self, macro->macroApply, macro->macroApply, rb1+3, rb2 ) ==0 ){
		DaoMacro_Delete( macro );
		return -1;
	}
	markers = DMap_New(D_STRING,0);

	for(i=start+2; i<rb1; i++){
		if( toks[i]->string.mbs[0] == '$' ){
			if( MAP_Find( markers, & toks[i]->string ) != NULL ){
				self->curLine = toks[i]->line;
				DaoParser_Error( self, DAO_CTW_REDEF_MAC_MARKER, & toks[i]->string );
				return 0;
			}
			MAP_Insert( markers, & toks[i]->string, 0 );
		}
	}
	DMap_Clear( markers );
	i = rb1+3;
	if( DString_EQ( & toks[start+2]->string, & toks[rb1+3]->string ) ) i ++;
	while( i < rb2 ){
		char ch = toks[i]->string.mbs[0];
		if( ch != '$' && ch != '\\' && ch != '\'' ){
			if( MAP_Find( markers, & toks[i]->string ) == NULL ){
				DArray_Append( macro->keyListApply, & toks[i]->string );
				MAP_Insert( markers, & toks[i]->string, 0 );
			}
		}
		i ++;
	}

	stops = DArray_New(D_TOKEN);
	DMacroGroup_SetStop( macro->macroMatch, stops );
	DMacroGroup_FindVariables( macro->macroMatch );
	DArray_Clear( stops );
	DMacroGroup_SetStop( macro->macroApply, stops );
	DaoNamespace_AddMacro( self->nameSpace, lang, & toks[start+2]->string, macro );
	DArray_Delete( stops );
	DMap_Delete( markers );
	return rb2;
}