#include "SynTree/Constant.h" #include "InitModel.h" #include #include #include namespace InitTweak { InitModelBuilder::InitModelBuilder( Declaration *_decl ) : taken( false ), decl( 0 ), building(0) { ObjectDecl *_odecl = dynamic_cast< ObjectDecl * >( _decl ); assert( _odecl != 0 ); Type *objectType = _odecl->get_type(); /* this to be replaced by dynamic dispatch */ if( dynamic_cast< BasicType * >(objectType) != 0 ) { if( building == 0 ) building = new SingleName; } else if( ReferenceToType *rt = dynamic_cast< ReferenceToType * >(objectType) ) { rt->accept( *this ); } else if( ArrayType *at = dynamic_cast< ArrayType * >(objectType) ) { at->accept( *this ); } else // if (tuples) std::cerr << "Got something else" << std::endl; if ( decl != 0 ) init(); } InitModelBuilder::~InitModelBuilder() { if( !taken ) { delete building; building = 0; } } void InitModelBuilder::init() { assert( decl != 0 ); decl->accept( *this ); } // Visitor interface void InitModelBuilder::visit( ArrayType *at ) { if( building == 0 ) building = new RangeAssociation(interpretDimension( at->get_dimension() )); decl = 0; return; } void InitModelBuilder::visit( StructInstType *st ) { if( building == 0 ) building = new PointAssociation; decl = st->get_baseStruct(); return; } void InitModelBuilder::visit( UnionInstType *ut ) { decl = ut->get_baseUnion(); return; } void InitModelBuilder::visit( EnumInstType * ) {} void InitModelBuilder::visit( StructDecl *aggregateDecl) { PointAssociation *pa = dynamic_cast< PointAssociation * >( building ); assert( pa != 0 ); std::list< Declaration * > mem = aggregateDecl->get_members(); for( std::list::iterator i = mem.begin(); i != mem.end(); i++ ) { pa->add_member( (*i)->get_name() ); InitModelBuilder rec(*i); pa->set_member( (*i)->get_name(), rec.grab_assoc() ); } return; } void InitModelBuilder::visit( UnionDecl *) {} void InitModelBuilder::visit( EnumDecl *) {} // InitModelBuilder::ConstantFolder void InitModelBuilder::ConstantFolder::visit( ConstantExpr *cnst ) { Constant *c = cnst->get_constant(); assert (c != 0); if ( BasicType *bt = dynamic_cast( c->get_type() ) ) { if( bt->isInteger() ) { // need more intelligence here, not necessarily base 10 value = std::strtol( c->get_value().c_str(), NULL, 10 ); return; } else std::cerr << "Basic type but not integer" << std::endl; } throw 0; } // InitModelFiller InitModelFiller::InitModelFiller( Association *_model, Initializer *_init, bool _topLevel ) : model( _model ), orgInit( _init ), topLevel( _topLevel ), next( 0 ) { //next = model.begin(); if ( orgInit != 0 ) init(); } void InitModelFiller::init() { assert( model != 0 ); // change it into a reference assert( orgInit != 0 ); orgInit->accept( *this ); } void InitModelFiller::visit( SingleInit *singleInit ) { std::list< Expression *> &des = singleInit->get_designators(); if( topLevel ) { assert ( des.empty() ); assert ( dynamic_cast< SingleName * >(model) != 0 ); try { model->add_single( next++, singleInit->get_value() ); } catch (...) { std::cerr << "Illegal initialization" << std::endl; } return; } if( des.empty() ) { assert( model != 0 ); try { model->add_single( next++, singleInit->get_value() ); } catch ( AssocException &e ) { throw SemanticError( "Illegal initialization: " + e.get_what() ); } catch ( ... ) { std::cerr << "Shouldn't be here" << std::endl; } return; } // not general enough (does not contend well with designated arrays) std::list desnames; std::transform( des.begin(), des.end(), back_inserter(desnames), Initializer::designator_name ); for ( std::list::iterator i = desnames.begin(); i != desnames.end(); i++ ) { try { next = model->add_single( *i, singleInit->get_value() ); next++; } catch ( AssocException &e ) { throw SemanticError( "Illegal initialization: " + e.get_what() ); } catch ( ... ) { std::cerr << "Shouldn't happen, check association" << std::endl; } } return; } void InitModelFiller::visit( ListInit *listInit ) { assert( listInit != 0 ); // designators std::list< Expression *> &des = listInit->get_designators(); std::list< Initializer *> &ini = listInit->get_initializers(); if (! des.empty() ) { if (topLevel) throw SemanticError( "Invalid initializer: designated at top level." ); std::list des2; std::copy (des.begin(), des.end(), back_inserter( des2 )); std::list< Expression * > empty; listInit->set_designators( empty ); for ( std::list::iterator i = des2.begin(); i != des2.end(); i++ ) { Association * newModel = 0; if( NameExpr *n = dynamic_cast< NameExpr * >( *i ) ) try { newModel = (*model)[ n->get_name() ]; } catch( AssocException &e ) { std::cerr << "Didn't find member: " << e.get_what() << std::endl; } else // if( RangeExpr *r = dynamic_cast< RangeExpr * >( *i ) ) std::cerr << "Invalid designator specification" << std::endl; InitModelFiller rec( newModel, listInit, true ); } } else if (topLevel) { topLevel = false; for ( std::list::iterator i = ini.begin(); i != ini.end(); i++ ) (*i)->accept(*this); } else // next available uninitialized member InitModelFiller rec( (*model)[next++], listInit, true ); } void InitUnspooler::visit( SingleName *single ) { assert(init == 0 && single != 0); std::list< Expression * > empty; init = new SingleInit( single->get_expr(), empty ); return; } void InitUnspooler::visit( PointAssociation *pa ) { assert( pa != 0 ); std::list< Initializer * > contents; for( int i = 0; i < pa->size(); i++ ) if ( (*pa)[i] != 0 ) { InitUnspooler rec; (*pa)[i]->accept( rec ); assert( rec.get_initializer() != 0 ); contents.push_back( rec.grab_initializer() ); } init = new ListInit( contents ); return; } } // namespace InitTweak