/* assumed to be called after parsing class body */ void DaoClass_DeriveObjectData( DaoClass *self ) { DaoType *type; DaoValue *value; DArray *parents, *offsets; DString *mbs; DNode *search; daoint i, id, perm, index, offset = 0; self->objDefCount = self->objDataName->size; offset = self->objDataName->size; mbs = DString_New(1); parents = DArray_New(0); offsets = DArray_New(0); DaoClass_Parents( self, parents, offsets ); for( i=0; i<self->superClass->size; i++){ if( self->superClass->items.pValue[i]->type == DAO_CLASS ){ DaoClass *klass = self->superClass->items.pClass[i]; /* for properly arrangement object data: */ for( id=0; id<klass->objDataName->size; id ++ ){ DString *name = klass->objDataName->items.pString[id]; DaoVariable *var = klass->instvars->items.pVar[id]; var = DaoVariable_New( var->value, var->dtype ); DArray_Append( self->objDataName, name ); DArray_Append( self->instvars, var ); DaoValue_MarkConst( (DaoValue*) var->value ); } offset += klass->objDataName->size; } } for(i=1; i<parents->size; i++){ DaoClass *klass = parents->items.pClass[i]; offset = offsets->items.pInt[i]; /* plus self */ if( klass->type == DAO_CLASS ){ /* For object data: */ for( id=0; id<klass->objDataName->size; id ++ ){ DString *name = klass->objDataName->items.pString[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 ); if( search == NULL ){ /* To not overide data and routine: */ index = LOOKUP_BIND( DAO_OBJECT_VARIABLE, perm, i, (offset+id) ); MAP_Insert( self->lookupTable, name, index ); } } } } self->derived = 1; DString_Delete( mbs ); DArray_Delete( parents ); DArray_Delete( offsets ); DaoObject_Init( & self->objType->value->xObject, NULL, 0 ); self->objType->value->xObject.trait &= ~DAO_VALUE_CONST; DaoValue_MarkConst( self->objType->value ); DaoValue_MarkConst( self->constants->items.pConst[1]->value ); /* ::default */ }
static void DaoObject_Print( DaoValue *self0, DaoProcess *proc, DaoStream *stream, DMap *cycData ) { int ec; char buf[50]; DaoObject *self = & self0->xObject; sprintf( buf, "[%p]", self ); if( self0 == self->defClass->objType->value ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, "[null]" ); return; } if( cycData != NULL && DMap_Find( cycData, self ) != NULL ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); return; } if( cycData ) MAP_Insert( cycData, self, self ); DString_SetChars( proc->mbstring, "serialize" ); DaoValue_Clear( & proc->stackValues[0] ); ec = DaoObject_InvokeMethod( self, proc->activeObject, proc, proc->mbstring, NULL,0,1,1 ); if( ec && ec != DAO_ERROR_FIELD_NOTEXIST ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->mbstring->chars, NULL ); }else if( ec == DAO_ERROR_FIELD_NOTEXIST || proc->stackValues[0] == NULL ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); }else{ DaoValue_Print( proc->stackValues[0], proc, stream, cycData ); } }
static void DaoClass_AddConst3( DaoClass *self, DString *name, DaoValue *data ) { DaoConstant *cst = DaoConstant_New( data ); DArray_Append( self->cstDataName, (void*)name ); DArray_Append( self->constants, cst ); DaoValue_MarkConst( cst->value ); if( data->type == DAO_ROUTINE && data->xRoutine.routHost != self->objType ){ if( data->xRoutine.attribs & DAO_ROUT_VIRTUAL ){ /* data->xRoutine.overloads == NULL */ if( self->vtable == NULL ) self->vtable = DHash_New(0,0); MAP_Insert( self->vtable, data, data ); } } }
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; }
static int DaoClass_AddConst2( DaoClass *self, DString *name, DaoValue *data, int s ) { int id = LOOKUP_BIND( DAO_CLASS_CONSTANT, s, 0, self->constants->size ); DaoNamespace *ns = self->classRoutine->nameSpace; if( data->type == DAO_ROUTINE && data->xRoutine.routHost != self->objType ){ if( data->xRoutine.overloads ){ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) data ); data = (DaoValue*) routs; } } MAP_Insert( self->lookupTable, name, id ); DaoClass_AddConst3( self, name, data ); return id; }
int DaoClass_AddObjectVar( DaoClass *self, DString *name, DaoValue *deft, DaoType *t, int s ) { int id; DNode *node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; if( deft == NULL && t ) deft = t->value; id = self->objDataName->size; MAP_Insert( self->lookupTable, name, LOOKUP_BIND( DAO_OBJECT_VARIABLE, s, 0, id ) ); DArray_Append( self->objDataName, (void*)name ); DArray_Append( self->instvars, DaoVariable_New( deft, t ) ); DaoValue_MarkConst( self->instvars->items.pVar[ id ]->value ); return id; }
static void DaoObject_Print( DaoValue *self0, DaoProcess *proc, DaoStream *stream, DMap *cycData ) { int ec = 0; char buf[50]; DaoObject *self = & self0->xObject; DaoValue *params[2]; DaoRoutine *meth; sprintf( buf, "[%p]", self ); if( self0 == self->defClass->objType->value ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, "[null]" ); return; } if( cycData != NULL && DMap_Find( cycData, self ) != NULL ){ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); return; } if( cycData ) MAP_Insert( cycData, self, self ); DaoValue_Clear( & proc->stackValues[0] ); params[0] = (DaoValue*) dao_type_string; params[1] = (DaoValue*) stream; meth = DaoClass_FindMethod( self->defClass, "(string)", NULL ); if( meth ){ ec = DaoProcess_Call( proc, meth, self0, params, 2 ); if( ec ) ec = DaoProcess_Call( proc, meth, self0, params, 1 ); }else{ meth = DaoClass_FindMethod( self->defClass, "serialize", NULL ); if( meth ) ec = DaoProcess_Call( proc, meth, self0, NULL, 0 ); } if( ec ){ DaoProcess_RaiseException( proc, daoExceptionNames[ec], proc->string->chars, NULL ); }else if( meth && proc->stackValues[0] ){ DaoValue_Print( proc->stackValues[0], proc, stream, cycData ); }else{ DaoStream_WriteString( stream, self->defClass->className ); DaoStream_WriteChars( stream, buf ); } }
/* get new element, old face list and create the element faces => return the new face list */ static FACE* create_faces (MEM *facmem, MEM *mapmem, MAP **faces, ELEMENT *ele, FACE *list) { FACE *fac, tmp; int n, m; m = neighs (ele->type); for (n = 0; n < m; n ++) { /* set up temporary face for to * be used as the map search key */ setup_face (ele, n, &tmp, 1); /* nodes sorted for map key comparisons */ fac = static_cast<FACE*>(MAP_Find (*faces, &tmp, face_compare)); /* is it there ? */ if (fac) /* was mapped already */ { /* set up element adjacency */ ele->adj [ele->neighs] = fac->ele; fac->ele->adj [fac->ele->neighs] = ele; fac->ele->neighs ++; ele->neighs ++; fac->ele = NULL; /* mark as the inner face (***) */ } else { fac = static_cast<FACE*>(MEM_Alloc (facmem)); fac->ele = ele; setup_face (ele, n, fac, 1); fac->index = n; /* local index */ MAP_Insert (mapmem, faces, fac, /* map by the type/nodes key */ fac, face_compare); fac->next = list; list = fac; } } return list; }
/* create mesh from a vector of nodes, element list in format => * {nuber of nodes, node0, node1, ..., material}, {REPEAT}, ..., 0 (end of list); and surface colors in format => * global surface, {number of nodes, node0, node1, ..., surface}, {REPEAT}, ..., 0 (end of list); */ MESH_DATA* MESH_Create (REAL (*nodes) [3], int *elements, int *surfaces) { int maximal_node, minimal_node, elements_count, faces_count, temp, *eleptr, n; REAL (*node) [3]; MEM *elemem, facmem, mapmem; ELEMENT *ele, *enx, *elist; FACE *fac, *cac, *gac, *flist; MAP *faces, *smap; MESH_DATA *msh; maximal_node = 0; minimal_node = INT_MAX; elements_count = 0; faces_count = 0; /* create mesh storage */ ERRMEM (msh = static_cast<MESH_DATA*>(MEM_CALLOC (sizeof (MESH_DATA)))); elemem = &msh->elemem; /* calculate elements */ for (eleptr = elements; eleptr [0]; eleptr += (eleptr [0]+2)) elements_count ++; MEM_Init (elemem, sizeof (ELEMENT), elements_count); MEM_Init (&facmem, sizeof (FACE), MEMCHUNK); MEM_Init (&mapmem, sizeof (MAP), MEMCHUNK); MEM_Init (&msh->mapmem, sizeof (MAP), MIN (elements_count, MEMCHUNK)); elist = NULL; flist = NULL; faces = NULL; /* create elements list & face adjacency map */ for (eleptr = elements; eleptr [0]; eleptr += (eleptr [0]+2)) { ASSERT ( eleptr [0] == 4 || /* tetrahedron */ eleptr [0] == 5 || /* pyramid */ eleptr [0] == 6 || /* wedge */ eleptr [0] == 8, /* hexahedron */ "ERROR: unsupported element type"); ele = create_element (elemem, eleptr); flist = create_faces (&facmem, &mapmem, &faces, ele, flist); ele->next = elist; elist = ele; /* node number extrema */ temp = maximal (eleptr); if (temp > maximal_node) maximal_node = temp; temp = minimal (eleptr); if (temp < minimal_node) minimal_node = temp; } /* calculate faces */ for (fac = flist; fac; fac = fac->next) if (fac->ele) faces_count ++; /* alocate additional storage */ MEM_Init (&msh->facmem, sizeof (FACE), faces_count); msh->nodes_count = (maximal_node - minimal_node + 1); ERRMEM (msh->nodes = static_cast<REAL(*)[3]>(malloc (sizeof (REAL [3]) * (msh->nodes_count)))); msh->surfeles_count = msh->bulkeles_count = 0; msh->surfeles = msh->bulkeles = NULL; /* set up elements */ for (ele = elist; ele; ele = enx) { enx = ele->next; if (minimal_node > 0) /* impose 0-based indexing */ { for (temp = 0; temp < ele->type; temp ++) ele->nodes [temp] -= minimal_node; } ele->prev = NULL; if (ele->neighs < neighs (ele->type)) /* surface element */ { msh->surfeles_count ++; ele->next = msh->surfeles; if (msh->surfeles) msh->surfeles->prev = ele; msh->surfeles = ele; } else /* bulk element */ { msh->bulkeles_count ++; ele->next = msh->bulkeles; if (msh->bulkeles) msh->bulkeles->prev = ele; msh->bulkeles = ele; } } /* create surfaces map => skip first element of 'surfaces' == the global surface kind */ for (eleptr = (surfaces + 1), smap = NULL, temp = 0; eleptr [0]; eleptr += (eleptr [0]+2), temp ++) { fac = static_cast<FACE*>(MEM_Alloc (&facmem)); ASSERT ( eleptr [0] == 3 || /* triangle */ eleptr [0] == 4, /* quad */ "ERROR: unsupported face type"); fac->type = eleptr [0]; for (n = 0; n < eleptr [0]; n ++) fac->nodes [n] = eleptr [n+1]; sort (fac->nodes, fac->nodes+fac->type-1); fac->color = eleptr [eleptr [0] + 1]; MAP_Insert (&mapmem, &smap, fac, /* map by the type/nodes key */ fac, face_compare); } /* set up nodes */ for (temp = minimal_node, node = msh->nodes; temp <= maximal_node; temp ++, node ++) { COPY (nodes [temp], *node); } /* set up faces */ for (fac = flist; fac; fac = fac->next) { if (fac->ele) /* see (***) */ { ele = fac->ele; cac = static_cast<FACE*>(MEM_Alloc (&msh->facmem)); setup_face (ele, fac->index, cac, 0); /* setup face nodes without sorting them */ cac->index = fac->index; cac->ele = fac->ele; setup_normal (msh->nodes, cac); /* calculate outer spatial normal */ cac->next = ele->faces; /* append element face list */ ele->faces = cac; /* set the mapped surface kind if possible => otherwise the global one */ gac = static_cast<FACE*>(MAP_Find (smap, fac, face_compare)); cac->color = (gac ? gac->color : surfaces [0]); } } /* create mesh face list */ for (ele = msh->surfeles; ele; ele = ele->next) { for (fac = ele->faces; fac; fac = fac->next) { fac->n = msh->faces; msh->faces = fac; } } /* clean up */ MEM_Release (&facmem); MEM_Release (&mapmem); return msh; }
/* Matching a macro to source tokens. * For each macro variable such as $EXP and $VAR etc. * the matched tokens are stored in a tree, in which the leaves * are corresponding to the matched tokens and the branches * corresponding to the repetition of the matchings. * * For example, * key1 { \( key2 ( \( key3 $EXPR , \) \+ ) ; \) \* } * key1 { key2 ( key3 A+1 , key3 B-2, ); key2 ( key3 C*3, key3 D/4, key3 E+5, ); } * * the matching will generate such tree: * * key1: | * | * \( key2 ... \) : __________|______________ * | | * | | * \( key3 ... \) : ____|____ _________|_________ * | | | | | * | | | | | * | | | | | * $EXPR: {A,+,1} {B,-,2} {C,*,3} {D,/,4} {E,+,5} */ static int DaoParser_MacroMatch( DaoParser *self, int start, int end, DMacroGroup *group, DMap *tokMap, int level, DArray *all, int indent[10] ) { DMacroUnit **units = (DMacroUnit**) group->units->items.pVoid; DMacroUnit *unit; DMacroGroup *grp; DaoToken **toks = self->tokens->items.pToken; DNode *kwnode; DMacroNode *node, *prev; int M, N = group->units->size; int i, j=0, k=0, m, min, from = start; int idt, gid = -1; /* printf( "MacroMatch\n" ); printf( "from = %i\n", from ); */ if( group->repeat != DMACRO_AUTO ){ level ++; for(j=0,M=group->variables->size; j<M; j++){ kwnode = MAP_Find( tokMap, & group->variables->items.pToken[j]->string ); prev = (DMacroNode*)( kwnode ? kwnode->value.pVoid : NULL ); node = DMacroNode_New( level==1, level ); node->group = group; DArray_Append( all, node ); MAP_Insert( tokMap, & group->variables->items.pToken[j]->string, node ); while( prev && prev->group != group->parent ) prev = prev->parent; if( prev ){ node->parent = prev; prev->isLeaf = 0; DArray_Append( prev->nodes, (void*) node ); } } } for(i=0; i<N; i++){ unit = units[i]; idt = unit->indent; #if 0 printf( "match unit %i (%i), type %i, from %i, end %i\n", i, N, unit->type, from, end ); if( unit->type < DMACRO_GRP ) printf( "marker: %s\n", unit->marker->string.mbs ); #endif if( from <0 ) return -100; if( from < end && idt && indent[idt] >=0 && toks[from]->cpos != indent[idt] ) return -22; if( from < end && idt && indent[idt] < 0 ) indent[idt] = toks[from]->cpos; switch( unit->type ){ case DMACRO_TOK : if( from >= end ) return -100; if( ! DaoToken_EQ( toks[from], unit->marker ) ) return -23; switch( toks[from]->name ){ case DTOK_LB : k = DaoParser_FindPairToken( self, DTOK_LB, DTOK_RB, from, end ); break; case DTOK_LSB : k = DaoParser_FindPairToken( self, DTOK_LSB, DTOK_RSB, from, end ); break; case DTOK_LCB : k = DaoParser_FindPairToken( self, DTOK_LCB, DTOK_RCB, from, end ); break; default : break; } switch( toks[from]->name ){ case DTOK_LB : case DTOK_LCB : case DTOK_LSB : if( k <0 ) return -3; grp = (DMacroGroup*) units[i+1]; j = DaoParser_MacroMatch( self, from+1, k, grp, tokMap, level, all, indent ); if( j > k ) return -4; from = k; i ++; break; default : from ++; break; } break; case DMACRO_BR : if( from >= end ) return -100; if( ! DaoToken_EQ( toks[from], unit->marker ) ) return -24; from ++; break; case DMACRO_EXP : case DMACRO_ID : case DMACRO_OP : case DMACRO_BL : case DMACRO_IBL : if( from >= end ) return -100; switch( unit->type ){ case DMACRO_EXP : self->curToken = from; j = DaoParser_ParseExpression( self, 0 ); if( j < 0 ) return -100; j += 1; min = j + unit->stops->size; for(k=0,M=unit->stops->size; k<M; k++){ DaoToken *stop = unit->stops->items.pToken[k]; m = DaoParser_FindOpenToken2( self, stop, from, end ); #if 0 //printf( "searching: %i %s %i\n", j, stop->mbs, end ); #endif if( min >= m && m >=0 ) min = m; } /* if there is extra tokens between expr and the first stop marker */ if( j < 0 || min > j+1 ) return -5; if( min < j ) j = min; break; case DMACRO_ID : if( toks[from]->type != DTOK_IDENTIFIER ) return -1; j = from +1; break; case DMACRO_OP : if( toks[from]->name < DTOK_ADD || toks[from]->name > DTOK_DECR ) return -1; j = from +1; break; case DMACRO_BL : j = end; min = j + unit->stops->size; for(k=0,M=unit->stops->size; k<M; k++){ DaoToken *stop = unit->stops->items.pToken[k]; m = DaoParser_FindOpenToken2( self, stop, from, end ); /* printf( "searching: %i %s %i\n", j, stop->mbs, tokPos[j] ); */ if( m < min && m >=0 ) min = m; } /* printf( "j = %i min = %i\n", j, min ); */ if( min > j ) return -5; j = min; break; case DMACRO_IBL : k = toks[from]->line; m = toks[from]->cpos; j = from; while( j > start && (int)toks[j-1]->line == k ) j -= 1; if( j < from ) m = toks[j]->cpos + 1; j = from + 1; while( j < end && toks[j]->cpos >= m ) j += 1; /* printf( "end = %i, j = %i\n", end, j ); */ break; } /* key1 { \( key2 ( \( key3 $EXPR , \) \+ ) ; \) \* } * key1 { key2 ( key3 A , key3 B, ) ; key2 ( key3 C, key3 D, ) ; } * { level_1: { level_2, isLeaf: { A, B } }, { level_2, isLeaf: { C, D } } } */ kwnode = MAP_Find( tokMap, & unit->marker->string ); prev = (DMacroNode*) kwnode->value.pVoid; while( prev && prev->group != group ) prev = prev->parent; node = DMacroNode_New( 1, level+1 ); node->group = group; DArray_Append( all, node ); MAP_Insert( tokMap, & unit->marker->string, node ); node->parent = prev; if( prev ) DArray_Append( prev->nodes, node ); for(k=from; k<j; k++) DArray_Append( node->leaves, toks[k] ); /* DMacroNode_Print( node ); kwnode = DMap_Find( tokMap, (void*)unit->marker ); node = (DMacroNode*) kwnode->value.pVoid; while( node->parent ) node = node->parent; printf( "\n" ); */ from = j; break; case DMACRO_GRP : case DMACRO_ALT : grp = (DMacroGroup*) unit; j = DaoParser_MacroMatch( self, from, end, grp, tokMap, level, all, indent ); switch( grp->repeat ){ case DMACRO_AUTO : case DMACRO_ONE : if( from >= end ) return -100; if( j <0 && group->type != DMACRO_ALT ) return -6; if( j >=0 ){ from = j; gid = i; } break; case DMACRO_ZERO : if( j >=0 && group->type != DMACRO_ALT ) return -7; if( j <0 ) gid = i; break; case DMACRO_ZERO_OR_ONE : if( j >=0 && group->type != DMACRO_ALT ) from = j; gid = i; break; case DMACRO_ZERO_OR_MORE : gid = i; while( j >=0 ){ from = j; j = DaoParser_MacroMatch( self, from, end, grp, tokMap, level, all, indent ); } break; case DMACRO_ONE_OR_MORE : if( from >= end ) return -100; if( j <0 && group->type != DMACRO_ALT ) return -8; while( j >=0 ){ gid = i; from = j; j = DaoParser_MacroMatch( self, from, end, grp, tokMap, level, all, indent ); } break; } break; default : return -9; } #if 0 printf( "end = %i, j = %i, %i %i\n", end, from, unit->type, DMACRO_IBL ); //if( unit->type == DMACRO_IBL && from >= end ) break; #endif if( group->type == DMACRO_ALT && gid >=0 ) break; } if( group->repeat != DMACRO_AUTO ) level --; if( group->type == DMACRO_ALT && gid <0 ) return -1; return from; }
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; }
/* // 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; }
/* communicate objects using point to point communication */ int COMOBJS (MPI_Comm comm, int tag, OBJ_Pack pack, void *data, OBJ_Unpack unpack, COMOBJ *send, int nsend, COMOBJ **recv, int *nrecv) /* recv is contiguous => free (*recv) releases all memory */ { COMDATA *send_data, *recv_data, *cd, *cc; int recv_count, i, n, ret; COMOBJ *co; MAP *map; MEM mem; ERRMEM (send_data = malloc (nsend * sizeof (COMDATA))); MEM_Init (&mem, sizeof (MAP), MAX (nsend, 64)); /* pack objects */ for (i = 0, cd = send_data, co = send, map = NULL; i < nsend; i ++, cd ++, co ++) { int isize = 0, dsize = 0; cd->rank = co->rank; if ((cc = MAP_Find (map, co->o, NULL))) /* same object was already packed */ { cd->ints = cc->ints; cd->doubles = cc->doubles; cd->i = cc->i; cd->d = cc->d; } else { cd->ints = 0; cd->doubles = 0; cd->i = NULL; cd->d = NULL; pack (co->o, &dsize, &cd->d, &cd->doubles, &isize, &cd->i, &cd->ints); MAP_Insert (&mem, &map, co->o, cd, NULL); } } /* send and receive packed data */ if (tag == INT_MIN) ret = COMALL (comm, send_data, nsend, &recv_data, &recv_count); /* all to all */ else ret = COM (comm, tag, send_data, nsend, &recv_data, &recv_count); /* point to point */ #if PARDEBUG { int debug_send_count, *ip, *jp, ii [2], jj [2]; COMDATA *debug_send_data; double *qq, *pp; /* send backwards */ if (tag == INT_MIN) COMALL (comm, recv_data, recv_count, &debug_send_data, &debug_send_count); else COM (comm, tag, recv_data, recv_count, &debug_send_data, &debug_send_count); ii[0] = 0, ii[1] = 0; jj[0] = 0, jj[1] = 0; do { ip = next_int (send_data, nsend, ii); jp = next_int (debug_send_data, debug_send_count, jj); if (ip && jp) { ASSERT_DEBUG (*ip == *jp, "Integer values mismatch"); } else { ASSERT_DEBUG (!ip && !jp, "Integer count mismatch"); } } while (ip && jp); ii[0] = 0, ii[1] = 0; jj[0] = 0, jj[1] = 0; do { qq = next_double (send_data, nsend, ii); pp = next_double (debug_send_data, debug_send_count, jj); if (qq && pp) { ASSERT_DEBUG (*qq == *pp, "Double values mismatch"); } else { ASSERT_DEBUG (!qq && !pp, "Double count mismatch"); } } while (qq && pp); free (debug_send_data); } #endif if (recv_count) { *nrecv = recv_count; ERRMEM (*recv = malloc ((*nrecv) * sizeof (COMOBJ))); /* unpack received objects */ for (n = i = 0, cd = recv_data, co = *recv; i < recv_count; i ++, cd ++) { int ipos = 0, dpos = 0; do { if (n == *nrecv) { *nrecv *= 2; /* resize the receive buffer */ ERRMEM (*recv = realloc (*recv, (*nrecv) * sizeof (COMOBJ))); co = *recv + n; /* and reset the current pointer */ } co->rank = cd->rank; co->o = unpack (data, &dpos, cd->d, cd->doubles, &ipos, cd->i, cd->ints); co ++; n ++; } while (ipos < cd->ints || dpos < cd->doubles); /* while something is left to unpack */ } /* truncate output */ if (n) ERRMEM (*recv = realloc (*recv, n * sizeof (COMOBJ))); *nrecv = n; } else { *recv = NULL; *nrecv = 0; } /* cleanup */ for (MAP *item = MAP_First (map); item; item = MAP_Next (item)) { cd = item->data; free (cd->i); free (cd->d); } MEM_Release (&mem); free (send_data); free (recv_data); /* contiguous */ return ret; }
/* 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 ); }
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; }
/* read new bodies data */ static void read_new_bodies (DOM *dom, PBF *bf) { #if HDF5 double time, start, end; PBF_Time (bf, &time); /* back up time frame from outside of this function */ PBF_Limits (bf, &start, &end); PBF_Seek (bf, start); do { for (PBF *f = bf; f; f = f->next) { int ipos = 0, ints; int dpos = 0, doubles; double *d; int *i; int k, n; BODY *bod; if (PBF_Has_Group (f, "NEWBOD") == 0) continue; /* don't try to read if there are no new bodies stored */ PBF_Push (f, "NEWBOD"); PBF_Int2 (f, "count", &n, 1); PBF_Int2 (f, "ints", &ints, 1); ERRMEM (i = malloc (sizeof (int [ints]))); PBF_Int2 (f, "i", i, ints); PBF_Int2 (f, "doubles", &doubles, 1); ERRMEM (d = malloc (sizeof (double [doubles]))); PBF_Double2 (f, "d", d, doubles); for (k = 0; k < n; k ++) { bod = BODY_Unpack (dom->solfec, &dpos, d, doubles, &ipos, i, ints); if (!MAP_Find (dom->allbodies, (void*) (long) bod->id, NULL)) { MAP_Insert (&dom->mapmem, &dom->allbodies, (void*) (long) bod->id, bod, NULL); /* all bodies from all times */ } else BODY_Destroy (bod); /* FIXME: bodies created in input files at time > 0; FIXME: perhaps there is no need of moving GLV to the fist lng_RUN call, FIXME: but rather bodies created in Python should not be put into the 'dom->newb' set; FIXME: this way, as now, all Python created bodies will be anyway read at time 0 */ } free (d); free (i); PBF_Pop (f); } } while (PBF_Forward (bf, 1)); dom->allbodiesread = 1; /* mark as read */ PBF_Seek (bf, time); /* seek to the backed up time again */ #else char *path, *ext; FILE *file; int m, n; XDR xdr; if (dom->solfec->verbose) printf ("Reading all bodies ...\n"); dom->allbodiesread = 1; /* mark as read */ path = SOLFEC_Alloc_File_Name (dom->solfec, 16); ext = path + strlen (path); for (m = 0; bf; bf = bf->next) m ++; /* count input files */ for (n = 0; n < m; n ++) { if (n || m > 1) { sprintf (ext, ".bod.%d", n); if (!(file = fopen (path, "r"))) continue; /* no new bodies for this rank */ } else /* n == 0 && m == 1 */ { sprintf (ext, ".bod.%d", n); if (!(file = fopen (path, "r"))) /* either prallel with "mpirun -np 1" */ { sprintf (ext, ".bod"); if (!(file = fopen (path, "r"))) continue; /* or serial */ } } xdrstdio_create (&xdr, file, XDR_DECODE); int ipos, ints, *i, dpos, doubles; double *d; BODY *bod; for (;;) { if (xdr_int (&xdr, &doubles)) { ERRMEM (d = malloc (sizeof (double [doubles]))); if (xdr_vector (&xdr, (char*)d, doubles, sizeof (double), (xdrproc_t)xdr_double)) { if (xdr_int (&xdr, &ints)) { ERRMEM (i = malloc (sizeof (int [ints]))); if (xdr_vector (&xdr, (char*)i, ints, sizeof (int), (xdrproc_t)xdr_int)) { ipos = dpos = 0; bod = BODY_Unpack (dom->solfec, &dpos, d, doubles, &ipos, i, ints); if (!MAP_Find (dom->allbodies, (void*) (long) bod->id, NULL)) { MAP_Insert (&dom->mapmem, &dom->allbodies, (void*) (long) bod->id, bod, NULL); } else BODY_Destroy (bod); /* FIXME: bodies created in input files at time > 0; FIXME: perhaps there is no need of moving GLV to the fist lng_RUN call, FIXME: but rather bodies created in Python should not be put into the 'dom->newb' set; FIXME: this way, as now, all Python created bodies will be anyway read at time 0 */ free (d); free (i); } else { free (d); free (i); break; } } else { free (d); break; } } else { free (d); break; } } else break; } xdr_destroy (&xdr); fclose (file); } free (path); #endif }
/* read domain state */ void dom_read_state (DOM *dom, PBF *bf) { BODY *bod, *next; int ncon; /* clear contacts */ MAP_Free (&dom->mapmem, &dom->idc); MEM_Release (&dom->conmem); dom->con = NULL; dom->ncon = 0; /* read all bodies if needed */ if (!dom->allbodiesread) read_new_bodies (dom, bf); /* mark all bodies as absent */ for (bod = dom->bod; bod; bod = bod->next) bod->flags |= BODY_ABSENT; SET *usedlabel = NULL; for (; bf; bf = bf->next) { if (PBF_Label (bf, "DOM")) { /* read iover */ int iover = 2; if (PBF_Label (bf, "IOVER")) { PBF_Int (bf, &iover, 1); } /* read time step */ ASSERT (PBF_Label (bf, "STEP"), ERR_FILE_FORMAT); PBF_Double (bf, &dom->step, 1); /* read constraints merit */ ASSERT (PBF_Label (bf, "MERIT"), ERR_FILE_FORMAT); PBF_Double (bf, &dom->merit, 1); /* read body states */ ASSERT (PBF_Label (bf, "BODS"), ERR_FILE_FORMAT); int nbod; PBF_Int (bf, &nbod, 1); for (int n = 0; n < nbod; n ++) { unsigned int id; PBF_Uint (bf, &id, 1); bod = MAP_Find (dom->idb, (void*) (long) id, NULL); if (bod == NULL) /* pick from all bodies set */ { ASSERT_DEBUG_EXT (bod = MAP_Find (dom->allbodies, (void*) (long) id, NULL), "Body id invalid"); if (bod->label) { MAP *node = MAP_Find_Node (dom->lab, bod->label, (MAP_Compare)strcmp); if (node) { node->data = bod; /* body fregments can inherit labels */ SET_Insert (NULL, &usedlabel, bod->label, (SET_Compare)strcmp); } else MAP_Insert (&dom->mapmem, &dom->lab, bod->label, bod, (MAP_Compare) strcmp); } MAP_Insert (&dom->mapmem, &dom->idb, (void*) (long) bod->id, bod, NULL); bod->next = dom->bod; if (dom->bod) dom->bod->prev = bod; dom->bod = bod; bod->dom = dom; dom->nbod ++; } BODY_Read_State (bod, bf, iover); bod->flags &= ~BODY_ABSENT; } /* read constraints */ ASSERT (PBF_Label (bf, "CONS"), ERR_FILE_FORMAT); PBF_Int (bf, &ncon, 1); for (int n = 0; n < ncon; n ++) { CON *con; con = read_constraint (dom, iover, bf); MAP_Insert (&dom->mapmem, &dom->idc, (void*) (long) con->id, con, NULL); con->next = dom->con; if (dom->con) dom->con->prev = con; dom->con = con; } dom->ncon += ncon; } } /* remove absent bodies */ for (bod = dom->bod; bod; bod = next) { next = bod->next; if (bod->flags & BODY_ABSENT) { if (bod->label && !SET_Contains (usedlabel, bod->label, (SET_Compare)strcmp)) MAP_Delete (&dom->mapmem, &dom->lab, bod->label, (MAP_Compare) strcmp); MAP_Delete (&dom->mapmem, &dom->idb, (void*) (long) bod->id, NULL); if (bod->next) bod->next->prev = bod->prev; if (bod->prev) bod->prev->next = bod->next; else dom->bod = bod->next; dom->nbod --; } } SET_Free (NULL, &usedlabel); /* attach constraints to bodies */ dom_attach_constraints (dom); }
int DaoClass_AddType( DaoClass *self, DString *name, DaoType *tp ) { DNode *node = MAP_Find( self->abstypes, name ); if( node == NULL ) MAP_Insert( self->abstypes, name, tp ); return 1; }
bool DaoxDebugger::EditContinue ( DaoProcess *process, int newEntryLine, QList<int> & lineMap, QStringList & newCodes, QStringList & routCodes ) { DaoRoutine *oldrout = process->activeRoutine; int i, j, k, dest = 0; //printf( "=======%s\n", routCodes.join("\n").toLocal8Bit().data() ); //printf( "=======%s\n", newCodes.join("\n").toLocal8Bit().data() ); if( routCodes.size() == newCodes.size() ){ DaoLexer *lexer = DaoLexer_New(); bool eq = true; for(i=0; i<routCodes.size(); i++){ QString s1 = NormalizeCodes( routCodes[i], lexer ); QString s2 = NormalizeCodes( newCodes[i], lexer ); if( s1 != s2 ){ eq = false; break; } } DaoLexer_Delete( lexer ); if( eq ) return true; } QString codes = newCodes.join( "\n" ); DaoParser *parser = DaoParser_New(); DaoRoutine *routine = DaoRoutine_New( oldrout->nameSpace, oldrout->routHost, 1 ); routine->routType = oldrout->routType; routine->parCount = oldrout->parCount; routine->attribs = oldrout->attribs; routine->defLine = oldrout->defLine; parser->routine = routine; parser->nameSpace = routine->nameSpace = oldrout->nameSpace; parser->vmSpace = oldrout->nameSpace->vmSpace; DString_Assign( parser->fileName, oldrout->nameSpace->name ); routine->body->codeStart = oldrout->body->codeStart; routine->body->codeEnd = oldrout->body->codeStart + newCodes.size() + 1; parser->regCount = routine->parCount; parser->levelBase = oldrout->defLine != 0; bool res = DaoParser_LexCode( parser, codes.toLocal8Bit().data(), 1 ); for(i=0; i<(int)parser->tokens->size; i++){ parser->tokens->items.pToken[i]->line += routine->body->codeStart; } for(i=0; i<(int)oldrout->body->defLocals->size; i++){ DaoToken *tok = oldrout->body->defLocals->items.pToken[i]; if( tok->index >= oldrout->parCount || tok->type ==0 ) break; MAP_Insert( DList_Top( parser->lookupTables ), & tok->string, i ); DList_Append( routine->body->defLocals, tok ); } res = res && DaoParser_ParseRoutine( parser ); DaoParser_Delete( parser ); if( res == false ){ DaoRoutine_Delete( routine ); return false; } if( (process->stackSize - process->stackTop) < (routine->body->regCount + DAO_MAX_PARAM) ){ DaoProcess_PushFrame( process, routine->body->regCount ); DaoProcess_PopFrame( process ); } DaoType **regTypes = routine->body->regType->items.pType; DaoValue **newValues = process->activeValues; DaoValue **oldValues = (DaoValue**)calloc( oldrout->body->regCount, sizeof(DaoValue*) ); memcpy( oldValues, newValues, oldrout->body->regCount * sizeof(DaoValue*) ); memset( newValues, 0, oldrout->body->regCount * sizeof(DaoValue*) ); DaoProcess_InitTopFrame( process, routine, process->activeObject ); #if 0 DaoStream *stream = DaoStream_New(); DaoRoutine_PrintCode( oldrout, stream ); DaoRoutine_PrintCode( routine, stream ); #endif regmap.clear(); for(i=0; i<oldrout->parCount; i++) regmap[i] = i; DaoVmCode *oldVMC = oldrout->body->vmCodes->data.codes; DaoVmCode *newVMC = routine->body->vmCodes->data.codes; DaoVmCodeX **oldAnnot = oldrout->body->annotCodes->items.pVmc; DaoVmCodeX **newAnnot = routine->body->annotCodes->items.pVmc; int M = oldrout->body->vmCodes->size; int N = routine->body->vmCodes->size; j = k = 0; for(i=0; i<lineMap.size(); i++){ QList<DaoVmCode> oldLineCodes; QList<DaoVmCode> newLineCodes; if( lineMap[i] <0 ) continue; int old = lineMap[i] + oldrout->body->codeStart + 1; int niu = i + routine->body->codeStart + 1; //printf( "%3i %3i: %3i %3i; %3i %3i\n", j, k, i, niu, lineMap[i], old ); while( j<M && oldAnnot[j]->line < old ) ++j; while( k<N && newAnnot[k]->line < niu ) ++k; while( j<M && oldAnnot[j]->line == old ){ oldLineCodes.append( oldVMC[j] ); ++j; } while( k<N && newAnnot[k]->line == niu ){ newLineCodes.append( newVMC[k] ); ++k; } Matching( oldLineCodes, newLineCodes ); } QMap<int,int>::iterator it, end = regmap.end(); for(it=regmap.begin(); it != end; ++it){ j = it.key(); i = it.value(); DaoValue_Move( oldValues[j], & newValues[i], regTypes[i] ); } int offset = 0; if( newEntryLine <0 ){ DaoVmCodeX **annotCodes = oldrout->body->annotCodes->items.pVmc; int entry = (process->activeCode - process->topFrame->codes) + 1; int entryline = oldrout->body->annotCodes->items.pVmc[entry]->line; /* if the entry line is NOT modified, use it */ entryline -= oldrout->body->codeStart + 1; for(i=0; i<lineMap.size(); i++) if( lineMap[i] == entryline ) break; int newEntryLine = i < lineMap.size() ? i : -1; if( newEntryLine >=0 ){ entryline += oldrout->body->codeStart + 1; while( (--entry) >=0 && annotCodes[entry]->line == entryline ) offset ++; } /* if the entry line IS modified, set the entry line to the first modified line */ if( newEntryLine <0 ){ for(i=0; i<lineMap.size(); i++) if( lineMap[i] <0 ) break; newEntryLine = i; } /* if the entry line is manually set: */ newEntryLine += routine->body->codeStart + 1; } //XXX GC_ShiftRC( routine, oldrout ); GC_IncRC( routine ); oldrout->body->revised = routine; process->activeRoutine = routine; process->activeTypes = regTypes; process->topFrame->codes = routine->body->vmCodes->data.codes; ResetExecution( process, newEntryLine, offset ); i = newCodes.size() - routCodes.size(); DaoNS_UpdateLineInfo( routine->nameSpace, routine->body->codeStart, i ); return true; }
void DaoClass_AddOverloadedRoutine( DaoClass *self, DString *signature, DaoRoutine *rout ) { MAP_Insert( self->ovldRoutMap, signature, rout ); }