/* 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 */ }
int DaoClass_GetData( DaoClass *self, DString *name, DaoValue **value, DaoClass *thisClass ) { DaoValue *p = NULL; DNode *node = MAP_Find( self->lookupTable, name ); int child = thisClass && DaoClass_ChildOf( thisClass, (DaoValue*)self ); int sto, perm, up, id; *value = NULL; if( ! node ) return DAO_ERROR_FIELD_NOTEXIST; perm = LOOKUP_PM( node->value.pInt ); sto = LOOKUP_ST( node->value.pInt ); up = LOOKUP_UP( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( self == thisClass || perm == DAO_DATA_PUBLIC || (child && perm >= DAO_DATA_PROTECTED) ){ switch( sto ){ case DAO_CLASS_VARIABLE : p = self->variables->items.pVar[id]->value; break; case DAO_CLASS_CONSTANT : p = self->constants->items.pConst[id]->value; break; default : return DAO_ERROR_FIELD; } if( p ) *value = p; }else{ return DAO_ERROR_FIELD_NOTPERMIT; } return 0; }
static int DaoClass_MapIndex( DaoClass *mixin, int st, int id, DMap *mixed ) { int offset = 0; DaoClass *mx = DaoClass_FindMixin( mixin, st, id, & offset ); DNode *it = DMap_Find( mixed, mx ); if( it != NULL ) it = MAP_Find( it->value.pMap, LOOKUP_BIND( st, 0, 0, id-offset ) ); if( it != NULL ) return LOOKUP_ID( it->value.pInt ); return id; }
void DaoClass_MakeInterface( DaoClass *self ) { daoint i, j; DaoType *tp; DaoRoutine *meth; DaoInterface *inter = self->inter; DMap *deftypes = DHash_New(0,0); DArray_Clear( self->inter->supers ); DMap_Clear( self->inter->methods ); if( self->parent && self->parent->type == DAO_CLASS ) DArray_Append( inter->supers, self->parent->xClass.inter ); for(i=0; i<self->cstDataName->size; ++i){ DString *name = self->cstDataName->items.pString[i]; DaoValue *value = self->constants->items.pConst[i]->value; DaoRoutine *rout = (DaoRoutine*) value; DNode *it; if( value->type != DAO_ROUTINE ) continue; if( value->xRoutine.attribs & DAO_ROUT_DECORATOR ) continue; it = MAP_Find( self->lookupTable, rout->routName ); if( it == NULL || LOOKUP_PM( it->value.pInt ) != DAO_DATA_PUBLIC ) continue; DMap_Reset( deftypes ); DMap_Insert( deftypes, rout->routHost, inter->abtype ); if( rout->overloads == NULL ){ tp = DaoType_DefineTypes( rout->routType, rout->nameSpace, deftypes ); if( tp == NULL ) continue; /* TODO: handle error; */ meth = DaoRoutine_New( rout->nameSpace, inter->abtype, 0 ); meth->attribs = rout->attribs; DString_Assign( meth->routName, rout->routName ); GC_ShiftRC( tp, meth->routType ); meth->routType = tp; DaoMethods_Insert( inter->methods, meth, meth->nameSpace, meth->routHost ); }else{ for(j=0; j<rout->overloads->routines->size; ++j){ DaoRoutine *rout2 = rout->overloads->routines->items.pRoutine[j]; if( rout2->attribs & DAO_ROUT_DECORATOR ) continue; tp = DaoType_DefineTypes( rout2->routType, rout2->nameSpace, deftypes ); if( tp == NULL ) continue; /* TODO: handle error; */ meth = DaoRoutine_New( rout2->nameSpace, inter->abtype, 0 ); meth->attribs = rout2->attribs; DString_Assign( meth->routName, rout->routName ); GC_ShiftRC( tp, meth->routType ); meth->routType = tp; DaoMethods_Insert( inter->methods, meth, meth->nameSpace, meth->routHost ); } } } DMap_Delete( deftypes ); }
int DaoClass_AddGlobalVar( DaoClass *self, DString *name, DaoValue *data, DaoType *t, int s ) { int size = self->variables->size; int id = LOOKUP_BIND( DAO_CLASS_VARIABLE, s, 0, size ); DNode *node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; if( data == NULL && t ) data = t->value; MAP_Insert( self->lookupTable, name, id ); DArray_Append( self->variables, DaoVariable_New( NULL, t ) ); DArray_Append( self->glbDataName, (void*)name ); if( data && DaoValue_Move( data, & self->variables->items.pVar[size]->value, t ) ==0 ) return -DAO_CTW_TYPE_NOMATCH; return id; }
int DaoClass_AddObjectVar( DaoClass *self, DString *name, DaoValue *deft, DaoType *t, int s ) { int id; DNode *node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; if( deft == NULL && t ) deft = t->value; id = self->objDataName->size; MAP_Insert( self->lookupTable, name, LOOKUP_BIND( DAO_OBJECT_VARIABLE, s, 0, id ) ); DArray_Append( self->objDataName, (void*)name ); DArray_Append( self->instvars, DaoVariable_New( deft, t ) ); DaoValue_MarkConst( self->instvars->items.pVar[ id ]->value ); return id; }
/* receive reactions updated by middle nodes */ static void receive_middle_reactions (DOM *dom, COMDATA *recv, int nrecv, MEM *setmem, SET **midupd) { COMDATA *ptr; int i, j, *k; CON *con; for (i = 0, ptr = recv; i < nrecv; i ++, ptr ++) { for (j = 0, k = ptr->i; j < ptr->ints; j ++, k ++) { ASSERT_DEBUG_EXT (con = MAP_Find (dom->conext, (void*) (long) (*k), NULL), "Invalid constraint id"); SET_Insert (setmem, midupd, con, NULL); } } }
/* receive external reactions */ static void receive_reactions (DOM *dom, COMDATA *recv, int nrecv) { COMDATA *ptr; int i, j, *k; double *R; CON *con; for (i = 0, ptr = recv; i < nrecv; i ++, ptr ++) { for (j = 0, k = ptr->i, R = ptr->d; j < ptr->ints; j ++, k ++, R += 3) { ASSERT_DEBUG_EXT (con = MAP_Find (dom->conext, (void*) (long) (*k), NULL), "Invalid constraint id"); COPY (R, con->R); con->state |= CON_DONE; } } }
/* 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; }
static int DaoParser_MacroApply( DaoParser *self, DArray *tokens, DMacroGroup *group, DMap *tokMap, DMap *used, int level, DString *tag, int pos0, int adjust ) { DMacroUnit **units = (DMacroUnit**) group->units->items.pVoid; DMacroUnit *unit; DMacroGroup *grp; DMacroNode *node, *node2; DArray *toks = DArray_New(D_TOKEN); DaoToken *tk = DaoToken_New(); DaoToken *tt = NULL; DNode *kwnode = NULL; DMap *check = NULL; DMap one = { NULL, 0, 0, 0 }; int M, N = group->units->size; int i, j, gid = -1; int repeated = 0; int start_mbs = -1; int start_wcs = -1; int squote, dquote; if( group->repeat != DMACRO_AUTO ) level ++; for( i=0; i<N; i++ ){ unit = units[i]; if( tokens->size >0 ) pos0 = tokens->items.pToken[ tokens->size -1 ]->line; self->curLine = pos0; /* printf( "apply unit %i: %i\n", i, unit->type ); */ switch( unit->type ){ case DMACRO_TOK : squote = unit->marker->type == DTOK_ESC_SQUO; dquote = unit->marker->type == DTOK_ESC_DQUO; if( (squote && start_mbs >=0) || (dquote && start_wcs >=0) ){ int qstart = squote ? start_mbs : start_wcs; tt = tokens->items.pToken[ qstart ]; for(j=qstart+1,M=tokens->size; j<M; j++){ DaoToken *jtok = tokens->items.pToken[j]; int t = j ? tokens->items.pToken[j-1]->type : 0; if( t == DTOK_IDENTIFIER && jtok->type == t ) DString_AppendChar( & tt->string, ' ' ); DString_Append( & tt->string, & jtok->string ); } if( squote ){ DString_AppendChar( & tt->string, '\'' ); DArray_Erase( tokens, start_mbs+1, tokens->size ); }else{ DString_AppendChar( & tt->string, '\"' ); DArray_Erase( tokens, start_wcs+1, tokens->size ); } start_mbs = -1; break; }else if( squote ){ start_mbs = tokens->size; DArray_Append( tokens, unit->marker ); tt = tokens->items.pToken[ start_mbs ]; tt->type = tt->name = DTOK_MBS; DString_SetMBS( & tt->string, "\'" ); break; }else if( dquote ){ start_wcs = tokens->size; DArray_Append( tokens, unit->marker ); tt = tokens->items.pToken[ start_wcs ]; tt->type = tt->name = DTOK_WCS; DString_SetMBS( & tt->string, "\"" ); break; } DArray_Append( tokens, unit->marker ); tokens->items.pToken[ tokens->size-1 ]->cpos += adjust; break; case DMACRO_VAR : DaoToken_Assign( tk, unit->marker ); DString_Append( & tk->string, tag ); DArray_Append( tokens, tk ); break; case DMACRO_EXP : case DMACRO_ID : case DMACRO_OP : case DMACRO_BL : case DMACRO_IBL : kwnode = MAP_Find( tokMap, & unit->marker->string ); if( kwnode ==NULL ){ DaoParser_Error( self, DAO_CTW_UNDEF_MAC_MARKER, & unit->marker->string ); goto Failed; } node = (DMacroNode*) kwnode->value.pVoid; kwnode = MAP_Find( used, unit ); if( kwnode == NULL ){ DMap_Insert( used, unit, & one ); kwnode = MAP_Find( used, unit ); } check = (DMap*) kwnode->value.pVoid; repeated = 1; /* printf( ">>>\n%s level %i: \n", unit->marker->string.mbs, level ); DMacroNode_Print( node ); printf( "\n" ); */ /* search a leaf */ node2 = DMacroNode_FindLeaf( node, check, level ); if( node2 ){ /* printf( "appending tokens\n" ); DMacroNode_Print( node2 ); printf( "\n" ); */ DArray_InsertArray( tokens, tokens->size, node2->leaves, 0, -1 ); DMap_Insert( check, node2, NULL ); /* DArray_Clear( node2->leaves ); */ }else{ DMacroNode_RemoveEmptyLeftBranch( node, level ); goto Failed; } break; case DMACRO_GRP : case DMACRO_ALT : grp = (DMacroGroup*) unit; DArray_Clear( toks ); j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust ); switch( grp->repeat ){ case DMACRO_AUTO : case DMACRO_ONE : if( j <0 && group->type != DMACRO_ALT ) goto Failed; repeated = (j>0); if( j >=0 ){ gid = i; DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } break; case DMACRO_ZERO_OR_ONE : gid = i; repeated = (j>0); if( j >=0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } break; case DMACRO_ZERO_OR_MORE : gid = i; repeated = (j>0); if( j >=0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } while( j >0 ){ DArray_Clear( toks ); j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust ); if( j >0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } } break; case DMACRO_ONE_OR_MORE : if( j <0 && group->type != DMACRO_ALT ) goto Failed; repeated = (j>0); if( j >=0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } while( j >0 ){ gid = i; DArray_Clear( toks ); j = DaoParser_MacroApply( self, toks, grp, tokMap, used, level, tag, pos0, adjust ); if( j >0 ){ DArray_InsertArray( tokens, tokens->size, toks, 0, -1 ); } } break; } break; default : goto Failed; } if( group->type == DMACRO_ALT && gid >=0 ) break; } if( group->repeat != DMACRO_AUTO ) level --; if( group->type == DMACRO_ALT && gid <0 ) goto Failed; DaoToken_Delete( tk ); DArray_Delete( toks ); return repeated; Failed : DaoToken_Delete( tk ); DArray_Delete( toks ); return -1; }
/* 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; }
int DaoClass_AddConst( DaoClass *self, DString *name, DaoValue *data, int s ) { int sto, pm, up, id; DNode *node = MAP_Find( self->lookupTable, name ); DaoNamespace *ns = self->classRoutine->nameSpace; DaoConstant *dest; DaoValue *value; assert( data != NULL ); if( node && LOOKUP_UP( node->value.pInt ) ){ /* inherited field: */ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ){ /* override inherited variable: */ DMap_EraseNode( self->lookupTable, node ); return DaoClass_AddConst( self, name, data, s ); } node->value.pInt = LOOKUP_BIND( sto, pm, 0, id ); dest = self->constants->items.pConst[id]; if( dest->value->type == DAO_ROUTINE && data->type == DAO_ROUTINE ){ /* Add the inherited routine(s) for overloading: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) dest->value ); DaoConstant *cst = DaoConstant_New( (DaoValue*) routs ); GC_ShiftRC( cst, dest ); self->constants->items.pConst[id] = cst; return DaoClass_AddConst( self, name, data, s ); }else{ /* Add the new constant: */ DaoConstant *cst = DaoConstant_New( data ); GC_ShiftRC( cst, dest ); self->constants->items.pConst[id] = cst; return node->value.pInt; } }else if( node ){ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ) return -DAO_CTW_WAS_DEFINED; dest = self->constants->items.pConst[id]; value = dest->value; if( value->type != DAO_ROUTINE || data->type != DAO_ROUTINE ) return -DAO_CTW_WAS_DEFINED; if( s > pm ) node->value.pInt = LOOKUP_BIND( sto, s, 0, id ); if( value->xRoutine.overloads == NULL || value->xRoutine.routHost != self->objType ){ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) value ); routs->trait |= DAO_VALUE_CONST; /* Add individual entry for the existing function: */ if( value->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, value ); GC_ShiftRC( routs, dest->value ); dest->value = (DaoValue*) routs; } if( data->xRoutine.overloads ){ DaoRoutines_Import( (DaoRoutine*) dest->value, data->xRoutine.overloads ); }else{ DaoRoutine *rout = (DaoRoutine*) data; DRoutines_Add( dest->value->xRoutine.overloads, rout ); if( self->vtable ) DaoRoutine_UpdateVtable( (DaoRoutine*)dest->value, rout, self->vtable ); /* Add individual entry for the new function: */ if( data->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, data ); } return node->value.pInt; } node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; return DaoClass_AddConst2( self, name, data, s ); }
/* 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 constraint state */ static CON* read_constraint (DOM *dom, int iover, PBF *bf) { SOLFEC_MODE mode = dom->solfec->mode; unsigned int id; CON *con; int kind; ERRMEM (con = MEM_Alloc (&dom->conmem)); PBF_Uint (bf, &con->id, 1); PBF_Int (bf, &kind, 1); con->kind = kind; PBF_Double (bf, con->R, 3); PBF_Double (bf, con->U, 3); if (iover > 1 && kind == CONTACT) { PBF_Double (bf, con->V, 3); } PBF_Double (bf, con->point, 3); PBF_Double (bf, con->base, 9); PBF_Double (bf, &con->merit, 1); PBF_Uint (bf, &id, 1); ASSERT_DEBUG_EXT (con->master = MAP_Find (dom->allbodies, (void*) (long) id, NULL), "Invalid master id"); PBF_Uint (bf, &id, 1); if (id) ASSERT_DEBUG_EXT (con->slave = MAP_Find (dom->allbodies, (void*) (long) id, NULL), "Invalid slave id"); if (kind == CONTACT) { con->state |= SURFACE_MATERIAL_Read_State (dom->sps, &con->mat, bf); PBF_Double (bf, &con->area, 1); PBF_Double (bf, &con->gap, 1); PBF_Int (bf, con->spair, 2); } if (iover < 4) { if (kind == RIGLNK || kind == VELODIR) PBF_Double (bf, con->Z, DOM_Z_SIZE); } else { if (kind == RIGLNK || kind == VELODIR || kind == SPRING) PBF_Double (bf, con->Z, DOM_Z_SIZE); } if (bf->parallel == PBF_ON) { if (mode == SOLFEC_READ) { PBF_Int (bf, &con->rank, 1); } else /* fake it => ranks are actually used in WRITE mode */ { int rank; PBF_Int (bf, &rank, 1); } } return con; }
DaoRoutine* DaoClass_GetOverloadedRoutine( DaoClass *self, DString *signature ) { DNode *node = MAP_Find( self->ovldRoutMap, signature ); if( node ) return (DaoRoutine*) node->value.pValue; return NULL; }
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; }
int DaoClass_AddConst( DaoClass *self, DString *name, DaoValue *data, int s ) { int fromMixin = 0; int fromParent = 0; int sto, pm, up, id; DNode *node = MAP_Find( self->lookupTable, name ); DaoNamespace *ns = self->classRoutine->nameSpace; DaoConstant *dest; DaoValue *value; if( node ){ id = LOOKUP_ID( node->value.pInt ); fromParent = LOOKUP_UP( node->value.pInt ); /* From parent classes; */ switch( LOOKUP_ST( node->value.pInt ) ){ /* Check if it is from mixins; */ case DAO_CLASS_CONSTANT : fromMixin = id >= self->cstMixinStart && id < self->cstMixinEnd; break; case DAO_CLASS_VARIABLE : fromMixin = id >= self->glbMixinStart && id < self->glbMixinEnd; break; case DAO_OBJECT_VARIABLE : fromMixin = id >= self->objMixinStart && id < self->objMixinEnd; break; } } assert( data != NULL ); if( fromParent || fromMixin ){ /* inherited field: */ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ){ /* override inherited variable: */ DMap_EraseNode( self->lookupTable, node ); return DaoClass_AddConst( self, name, data, s ); } node->value.pInt = LOOKUP_BIND( sto, pm, 0, id ); dest = self->constants->items.pConst[id]; if( dest->value->type == DAO_ROUTINE && data->type == DAO_ROUTINE ){ /* Add the inherited routine(s) for overloading: */ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*)dest->value ); DaoConstant *cst = DaoConstant_New( (DaoValue*) routs ); routs->trait |= DAO_VALUE_CONST; node->value.pInt = LOOKUP_BIND( sto, pm, 0, self->constants->size ); DArray_Append( self->cstDataName, (void*) name ); DArray_Append( self->constants, cst ); return DaoClass_AddConst( self, name, data, s ); }else{ /* Add the new constant: */ DaoConstant *cst = DaoConstant_New( data ); node->value.pInt = LOOKUP_BIND( sto, pm, 0, self->constants->size ); DArray_Append( self->cstDataName, (void*) name ); DArray_Append( self->constants, cst ); return node->value.pInt; } }else if( node ){ sto = LOOKUP_ST( node->value.pInt ); pm = LOOKUP_PM( node->value.pInt ); id = LOOKUP_ID( node->value.pInt ); if( sto != DAO_CLASS_CONSTANT ) return -DAO_CTW_WAS_DEFINED; dest = self->constants->items.pConst[id]; value = dest->value; if( value->type != DAO_ROUTINE || data->type != DAO_ROUTINE ) return -DAO_CTW_WAS_DEFINED; if( s > pm ) node->value.pInt = LOOKUP_BIND( sto, s, 0, id ); if( value->xRoutine.overloads == NULL || value->xRoutine.routHost != self->objType ){ DaoRoutine *routs = DaoRoutines_New( ns, self->objType, (DaoRoutine*) value ); routs->trait |= DAO_VALUE_CONST; /* Add individual entry for the existing function: */ if( value->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, value ); GC_ShiftRC( routs, dest->value ); dest->value = (DaoValue*) routs; } if( data->xRoutine.overloads ){ DaoRoutines_Import( (DaoRoutine*) dest->value, data->xRoutine.overloads ); }else{ DaoRoutine *rout = (DaoRoutine*) data; DRoutines_Add( dest->value->xRoutine.overloads, rout ); /* Add individual entry for the new function: */ if( data->xRoutine.routHost == self->objType ) DaoClass_AddConst3( self, name, data ); } return node->value.pInt; } node = MAP_Find( self->lookupTable, name ); if( node && LOOKUP_UP( node->value.pInt ) ) return -DAO_CTW_WAS_DEFINED; return DaoClass_AddConst2( self, name, data, s ); }
int DaoClass_GetDataIndex( DaoClass *self, DString *name ) { DNode *node = MAP_Find( self->lookupTable, name ); if( ! node ) return -1; return node->value.pInt; }
/* initialize domain state */ int dom_init_state (DOM *dom, PBF *bf, SET *subset) { 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); } ASSERT_TEXT (iover >= 3, "Output files are too old for INITIALISE_STATE to work"); /* read body states */ if (subset) { #if POSIX for (SET *item = SET_First (subset); item; item = SET_Next (item)) { regex_t xp; char *pattern = item->data; int error = regcomp (&xp, pattern, 0); if (error != 0) { char *message = get_regerror (error, &xp); fprintf (stderr, "-->\n"); fprintf (stderr, "Regular expression ERROR --> %s\n", message); fprintf (stderr, "<--\n"); regfree (&xp); free (message); return 0; } for (BODY *bod = dom->bod; bod; bod = bod->next) { if (bod->label && regexec (&xp, bod->label, 0, NULL, 0) == 0) { if (PBF_Label (bf, bod->label)) { BODY_Read_State (bod, bf, iover); } } } regfree (&xp); } #else ASSERT_TEXT (0, "Regular expressions require POSIX support --> recompile Solfec with POSIX=yes"); return 0; #endif } else { 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; BODY *bod; PBF_Uint (bf, &id, 1); bod = MAP_Find (dom->idb, (void*) (long) id, NULL); if (bod) /* update state of existing bodies only */ { BODY_Read_State (bod, bf, iover); } else /* mock read */ { int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); double *conf; double *velo; double energy[10]; int rank; ERRMEM (conf = malloc (sizeof(double) * rconf)); ERRMEM (velo = malloc (sizeof(double) * rdofs)); PBF_Double (bf, conf, rconf); PBF_Double (bf, velo, rdofs); PBF_Double (bf, energy, BODY_ENERGY_SIZE(rkind)); if (bf->parallel == PBF_ON) { PBF_Int (bf, &rank, 1); } free (conf); free (velo); } } } } } return 1; }
/* 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 ); }
/* 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_FindConst( DaoClass *self, DString *name ) { DNode *node = MAP_Find( self->lookupTable, name ); if( node == NULL || LOOKUP_ST( node->value.pInt ) != DAO_CLASS_CONSTANT ) return -1; return node->value.pInt; }
/* read state of an individual body */ int dom_read_body (DOM *dom, PBF *bf, BODY *bod) { /* read iover */ int iover = 2; if (PBF_Label (bf, "IOVER")) { PBF_Int (bf, &iover, 1); } if (bod->label) { for (; bf; bf = bf->next) { if (PBF_Label (bf, bod->label)) { BODY_Read_State (bod, bf, iover); return 1; } } } else { for (; bf; bf = bf->next) { if (PBF_Label (bf, "BODS")) { int nbod; PBF_Int (bf, &nbod, 1); for (int n = 0; n < nbod; n ++) { unsigned int id; BODY *obj; PBF_Uint (bf, &id, 1); ASSERT_DEBUG_EXT (obj = MAP_Find (dom->idb, (void*) (long) id, NULL), "Body id invalid"); if (bod->id == obj->id) { BODY_Read_State (bod, bf, iover); return 1; } else /* skip body and continue */ { BODY fake; ERRMEM (fake.conf = malloc (sizeof (double [BODY_Conf_Size (obj)]))); ERRMEM (fake.velo = malloc (sizeof (double [obj->dofs]))); fake.shape = NULL; BODY_Read_State (&fake, bf, iover); free (fake.conf); free (fake.velo); } } } } } return 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; }
/* map rigid onto FEM state */ int dom_rigid_to_fem (DOM *dom, PBF *bf, SET *subset) { 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); } ASSERT_TEXT (iover >= 3, "Output files are too old for RIGID_TO_FEM to work"); /* read body states */ if (subset) { #if POSIX for (SET *item = SET_First (subset); item; item = SET_Next (item)) { regex_t xp; char *pattern = item->data; int error = regcomp (&xp, pattern, 0); if (error != 0) { char *message = get_regerror (error, &xp); fprintf (stderr, "-->\n"); fprintf (stderr, "Regular expression ERROR --> %s\n", message); fprintf (stderr, "<--\n"); regfree (&xp); free (message); return 0; } for (BODY *bod = dom->bod; bod; bod = bod->next) { if (bod->label && regexec (&xp, bod->label, 0, NULL, 0) == 0) { if (PBF_Label (bf, bod->label)) { double conf [12], velo [6], energy [4]; int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); if (bod->kind == FEM && rkind == RIG) { PBF_Double (bf, conf, 12); PBF_Double (bf, velo, 6); PBF_Double (bf, energy, 4); BODY_From_Rigid (bod, conf, conf+9, velo, velo+3); } else { ASSERT_TEXT (((bod->kind == RIG || bod->kind == OBS) && (rkind == RIG || rkind == OBS)) || bod->kind == (unsigned)rkind, "Body kind mismatch when reading state"); ASSERT_TEXT (BODY_Conf_Size (bod) == rconf, "Body configuration size mismatch when reading state"); ASSERT_TEXT (bod->dofs == rdofs, "Body dofs size mismatch when reading state"); BODY_Read_State (bod, bf, 0); /* use 0 state to skip reading of rkind, rnconf, rdofs */ } } } } regfree (&xp); } #else ASSERT_TEXT (0, "Regular expressions require POSIX support --> recompile Solfec with POSIX=yes"); return 0; #endif } else { ASSERT (PBF_Label (bf, "BODS"), ERR_FILE_FORMAT); int nbod; PBF_Int (bf, &nbod, 1); for (int n = 0; n < nbod; n ++) { double conf [12], velo [6], energy [4]; unsigned int id; BODY *bod; int rank; PBF_Uint (bf, &id, 1); bod = MAP_Find (dom->idb, (void*) (long) id, NULL); if (bod) /* update state of existing bodies only */ { int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); if (bod->kind == FEM && rkind == RIG) { PBF_Double (bf, conf, 12); PBF_Double (bf, velo, 6); PBF_Double (bf, energy, 4); if (bf->parallel == PBF_ON) { PBF_Int (bf, &rank, 1); } BODY_From_Rigid (bod, conf, conf+9, velo, velo+3); } else { ASSERT_TEXT (((bod->kind == RIG || bod->kind == OBS) && (rkind == RIG || rkind == OBS)) || bod->kind == (unsigned)rkind, "Body kind mismatch when reading state"); ASSERT_TEXT (BODY_Conf_Size (bod) == rconf, "Body configuration size mismatch when reading state"); ASSERT_TEXT (bod->dofs == rdofs, "Body dofs size mismatch when reading state"); BODY_Read_State (bod, bf, 0); /* use 0 state to skip reading of rkind, rnconf, rdofs */ } } else /* mock read */ { int rkind; int rconf; int rdofs; PBF_Int (bf, &rkind, 1); PBF_Int (bf, &rconf, 1); PBF_Int (bf, &rdofs, 1); double *conf; double *velo; double energy[10]; int rank; ERRMEM (conf = malloc (sizeof(double) * rconf)); ERRMEM (velo = malloc (sizeof(double) * rdofs)); PBF_Double (bf, conf, rconf); PBF_Double (bf, velo, rdofs); PBF_Double (bf, energy, BODY_ENERGY_SIZE(rkind)); if (bf->parallel == PBF_ON) { PBF_Int (bf, &rank, 1); } free (conf); free (velo); } } } } } return 1; }
/* 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; }