/************************************************************************** * PROJECT: DEMETER Version 4.0 * MODULE: GENERATION * FILE: gen_non_inline.c * SYSTEM: C++ AT&T version 2.0 on sun, UNIX 4.3 BSD *-------------------------------------------------------------------------- * COPYRIGHT (c) 1990 * Prof. Karl J. Lieberherr *-------------------------------------------------------------------------- * AUTHOR: Walter Hursch * * DATE: November 16, 1990 * REVISED: December 6, 1990 * Mai 8, 1991 * fully incorporate multiple inheritance * including repeated inheritance * March 17, 1992 * Added class Text * April,1992 * Update because of GNU bugs * November 5, 1992 * Allow for component and external libraries * * *-------------------------------------------------------------------------- * DESCRIPTION: * Gen_non_inline generates all non-inline methods of all classes in * the data dictionary. For each class C the following items are ge- * nerated: * 1. for directory NOT-MOD/IMPL: * - C_DEM.C * generated methods: generated by method: * ------------------------------------------------------ * - constructor gen_constructor * - destructor gen_destructor * - rset_part1 gen_rset * - ... * - rset_partn gen_rset * - set_data_member gen_data_member * - get_data_member gen_data_member * - number_of_parts gen_data_member * - nummber_of_imm_parts gen_data_member * - pp * * 2. for directory NOT-MOD/INTER: * - C.h * * This file has formerly been called gen_inline.c (I don't know why). * The methods gen_data_member and set_data_member had been changed * so that they can also be used with multiple inheritance. * **************************************************************************/ /************************************************************************** Class dictionary used (intermediate notation): ;;; produced by extract-cd '(I-P1|O-P1)' ;;; produced by extract-cd 'O-P1' ; : O-P1: intermediate notation ;;; O-P1=I-P2 Demeter_in = Input. Input : Cd_graph *common*. Cd_graph = < adjacencies > Nlist(Adjacency) ["*terminal_sets*" Comma_list(Vertex) "."]. Adjacency = < source > Vertex < ns > Neighbors ["*inherits_from*" Comma_list(Term)] "." . Neighbors : Intermediate_ns *common*. Intermediate_ns : Repetit | Non_repetit *common*. Non_repetit : Instantiable | Abstract *common* List(Int_part). Instantiable = "instantiable=". Repetit = "repetition=" Term [ Non_empty]. Non_empty = "*non_empty*". Abstract = "abstract=". Int_part : Required_int_part | Optional_int_part *common* Labeled. Required_int_part = "*required*". Optional_int_part = "*optional*". Vertex = < vertex_name > DemIdent . Opt_labeled_term : Labeled *common* Term. Labeled = "<" < label_name > DemIdent ">" . ;; ;; 11/5/92 Update term to contain component and external terms ;; Term : Normal | CppTerm *common* Vertex TermRef ["(" Comma_list(Term) ")" ]. CppTerm = "$" . Normal = . TermRef : LocalRef | ModuleRef. ModuleRef : CompRef | LibRef *common* DemIdent. LocalRef = . CompRef = "@". LibRef = "@@". ; parameterized classes List(S) ~ {S}. Nlist(S) ~ S {S}. Comma_list(S) ~ S {"," S}. **************************************************************************/ #include "generate.h" #include #include #include extern int term_memberfunc( Universal* term1, Universal* term2 ); /*------------------------------------------------------------------------- * Method: void gen_non_inline( char* ) * * Takes the method down the CD graph to Adjacency_Nlist. * There the different tasks are executed and control is given further * down to generate the methods in C_DEM.C * *-----------------------------------------------------------------------*/ /* * demeter_in = < input > input . */ void Demeter_in::gen_non_inline( char* filename, char* top ) { input -> gen_non_inline( filename, top ); } /* * input : cd_graph *common* . */ void Input::gen_non_inline( char*, char* ) { } /* * cd_graph = < adjacencies > adjacency-Nlist * [ "*terminal_sets*" < terminal_sets > vertex-comma_List "." ] . */ void Cd_graph::gen_non_inline( char* filename, char* top ) { adjacencies -> gen_non_inline( filename, top ); } /* * adjacency-Nlist ~ adjacency { adjacency } . */ void Adjacency_Nlist::gen_non_inline( char* filename, char* top ) { // open file, check opening and write file ofstream outFile; outFile.open( filename, ios::out ); if ( !outFile ) { cerr << "Generate error: cannot open " << filename << " for output.\n"; exit( -1 ); } // write banner outFile << "/*-----------------------------------" << "------------------------------------\n" << " * DEMETER System Version 5.0\n" << " * Copyright (c) 1993 Northeastern University\n" << " *-----------------------------------" << "-------------------------------------\n" << " *\n" << " * GENERATED FILE -- DO NOT CHANGE !!\n" << " */\n\n" << "#include \"" << top << ".h\"\n\n"; Adjacency_list_iterator next_Adj( *this ); Adjacency_ each_Adj; while ( each_Adj = next_Adj() ) { each_Adj -> gen_non_inline( outFile, this ); } outFile.close(); } /*------------------------------------------------------------------------- * Methods: * void gen_non_inline( ofstream& outFile, Adjacency_Nlist* adjacencies ) * void gen_non_inline * ( ofstream& outFile, Adjacency_Nlist* adjacencies, Adjacency* adj ) * * Go further down the graph to Instantiable, Abstract and Repetit, where * the actual generation of the methods happens. *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::gen_non_inline ( ofstream& outFile, Adjacency_Nlist* adjacencies ) { DBG( cout << "IN Adjacency::gen_non_inline" << endl; ) ns -> gen_non_inline( outFile, adjacencies, this ); DBG( cout << "OUT Adjacency::gen_non_inline" << endl; ) } /* * neighbors : intermediate_ns *common* . */ void Neighbors::gen_non_inline ( ofstream&, Adjacency_Nlist*, Adjacency* ) { } /* * Intermediate_ns : * Repetit | * Non_repetit *common*. */ void Intermediate_ns::gen_non_inline ( ofstream&, Adjacency_Nlist*, Adjacency* ) { } /* * non_repetit : instantiable | abstract * *common* < intermed_ns > int_part-List . */ void Non_repetit::gen_non_inline ( ofstream& outFile, Adjacency_Nlist* adjacencies, Adjacency* adj ) { DBG( cout << "IN Non_repetit::gen_non_inline" << endl; ) char *class_name = adj -> get_class_name(); Intermediate_ns::gen_type( outFile, class_name ); intermed_ns -> gen_constructor( outFile, class_name ); intermed_ns -> gen_destructor( outFile, class_name ); intermed_ns -> gen_rset( outFile, class_name ); adj -> gen_data_member( outFile, adjacencies ); if ( MIFLAG ) { this -> gen_castdown_impl( outFile, adj, class_name ); } DBG( cout << "OUT Non_repetit::gen_non_inline" << endl; ) } void Non_repetit::gen_castdown_impl ( ofstream& outFile, Adjacency* adj, char* class_name ) { outFile << "void* " << class_name << "::_castdown(const char *target) const\n" << "{\n if (target == get_formal_type()) return (void*)this;\n\n" << " void* p;\n"; Term_list_iterator next_base( *(adj -> get_inherits_from()) ); Term_ base_class; while ( base_class = next_base() ) { // test which ancestor branch contains the target outFile << " if ( p = " << base_class -> get_class_name() << "::_castdown(target) ) return ( p );\n"; } outFile << " // still here?\n" << " return ( NULL );" << endl; outFile << "}\n" << endl; } /* * repetit = "repetition=" < repeated > term [ < non_empty > non_empty ] . */ void Repetit::gen_non_inline ( ofstream& outFile, Adjacency_Nlist *, Adjacency *adj ) { char* class_name = adj -> get_class_name(); /* already_generated stores all 'repeated terms' for which a g_compare function has already been generated. */ /* templates static Term_Comma_list *already_generated = new Term_Comma_list(); char* rep_name = repeated -> get_class_name(); if ( !already_generated -> member( repeated, term_memberfunc ) ) { outFile << "int g_compare( " << rep_name << "* obj1, " << rep_name << "* obj2" << " )\n{\n" << " return obj1 -> g_equal( obj2 );\n" << "}\n\n"; already_generated -> append( repeated ); } end templates */ Intermediate_ns::gen_type( outFile, class_name ); // constructor, was defined inline // destructor, not defined } /*------------------------------------------------------------------------- * Method: void gen_type( ofstream& outFile, char* class_name ) * * Generates the static data member type for all classes. *-----------------------------------------------------------------------*/ /* * Intermediate_ns : * Repetit | * Non_repetit *common*. */ void Intermediate_ns::gen_type( ofstream& outFile, char *class_name ) { outFile << "const char* " << class_name << "::type = \"" << class_name << "\";\n\n"; } /*------------------------------------------------------------------------- * Method: void gen_make_inst( ofstream& outFile, char* class_name ) * * Generates the make_instance member function for all classes. * Instantiable and Repetit classes create an object. Abstract classes * are not allowed to create objects. * * Fri Jul 9 10:47:49 1993 * This code is not used anymore since make_instance does not need to be * a member function. So we move this code over to make_instance\'s * responsibility. *-----------------------------------------------------------------------*/ /* * Intermediate_ns : * Repetit | * Non_repetit *common*. */ void Intermediate_ns::gen_make_inst( ofstream& outFile, char* class_name ) { outFile << "Universal* " << class_name << "::make_instance() \n" << "{\n" << " return ( new " << class_name << "() );\n" << "}\n" << endl; } void Abstract::gen_make_inst( ofstream& outFile, char* class_name ) { outFile << "Universal* " << class_name << "::make_instance() \n" << "{\n" << " cerr << \"Make_instance error: " << "cannot create object of \"\n" << " << \"abstract class: " << class_name << ".\" << endl; \n" << " exit (1);\n" << " return ( NULL ); // dummy return to please the compiler\n" << "}\n" << endl; } /*------------------------------------------------------------------------- * Method: void gen_constructor( ofstream& outFile, char* class_name ) * * Generates the constructor for Non_repetit classes. *-----------------------------------------------------------------------*/ /* * int_part-List ~ { int_part } . */ void Int_part_List::gen_constructor( ofstream& outFile, char* class_name ) { DBG( cout << "IN Int_part_List::gen_constructor" << endl; ) if ( !ctorIsDesired( class_name ) ) { return ; } Int_part_list_iterator next_Int_part1( *this ); Int_part_list_iterator next_Int_part2( *this ); Int_part_ each_Int_part; // constructor header outFile << class_name << "::" << class_name << "( "; // first element in list without comma each_Int_part = next_Int_part1(); if ( each_Int_part ) { outFile << each_Int_part -> get_class_name() << each_Int_part -> get_class_type() << " " << each_Int_part -> get_var_name() << "_in"; } // rest separated with commas while ( each_Int_part = next_Int_part1() ) { outFile << ", " << each_Int_part -> get_class_name() << each_Int_part -> get_class_type() << " " << each_Int_part -> get_var_name() << "_in"; } outFile << " )\n{\n"; // constructor body while ( each_Int_part = next_Int_part2() ) { outFile << " " << each_Int_part -> get_var_name() << " = " << each_Int_part -> get_var_name() << "_in;\n"; } outFile << "}\n\n"; DBG( cout << "OUT Int_part_List::gen_constructor" << endl; ) } /*------------------------------------------------------------------------- * Method: void gen_destructor( ofstream& outFile, char* class_name ) * * Generates the destructor for Non_repetit classes. *-----------------------------------------------------------------------*/ /* * int_part-List ~ { int_part } . */ void Int_part_List::gen_destructor( ofstream& outFile, char* class_name ) { Int_part_list_iterator next_Int_part( *this ); Int_part_ each_Int_part; // destructor header outFile << class_name << "::~" << class_name << "()\n{\n"; // Destructor body. // Destroying all parts is dangerous because of possible dangling // pointers. Leave garbage collection to the user. while ( each_Int_part = next_Int_part() ) { // outFile << " delete " << each_Int_part -> get_var_name() << ";\n"; } outFile << "}\n\n"; } /*------------------------------------------------------------------------- * Method: void gen_rset( ofstream& outFile, char* class_name ) * * Generates the method rset_part, where part is a data member of the * class at hand. * *-----------------------------------------------------------------------*/ /* * int_part-List ~ { int_part } . */ void Int_part_List::gen_rset( ofstream& outFile, char* class_name ) { Int_part_list_iterator next_Int_part( *this ); Int_part_ each_Int_part; char* part_class_name; char* part_class_type; char* part_var_name; // generate rsetter only for those parts that don not specify the read-only // or private keyword. while ( each_Int_part = next_Int_part() ) { if ( each_Int_part->get_accessorspec() == NULL ) { // generate rset only if neither private nor read-only part_class_name = each_Int_part -> get_class_name(); part_class_type = each_Int_part -> get_class_type(); part_var_name = each_Int_part -> get_var_name(); // rset header outFile << part_class_name << part_class_type << " " << endl << class_name << "::rset_" << part_var_name << "( " << part_class_name << part_class_type << " " << "new_" << part_var_name << " )\n{" << endl; outFile << " " << part_class_name << part_class_type << " " << "_old_" << part_var_name << " = " << part_var_name << ";\n"; outFile << " " << part_var_name << " = new_" << part_var_name << ";\n"; outFile << " return( _old_" << part_var_name << " );\n}\n" << endl; } } } /*------------------------------------------------------------------------- * Method: void gen_data_member * ( ofstream& outFile, Adjacency_Nlist* adjacencies, Adjacency* adj ) * * Generates for class C with name class_name the methods: * - C::set_data_member( int, Universal* ) * - C::get_data_member( int ) * - C::number_of_parts() * - C::number_of_imm_parts() * *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::gen_data_member ( ofstream& outFile, Adjacency_Nlist* adjacencies ) { DBG( cout << "IN Adjacency::gen_data_member" << endl ); char *class_name = this -> get_class_name(); int number_of_parts = 0; int number_of_imm_parts = 0; this -> count_imm_parts( number_of_imm_parts ); // generate method Universal* C::get_data_member( int, Universal* ) outFile << "Universal* " << class_name << "::get_data_member( int index ) const\n{\n" << " switch( index ) {\n"; // get all data members // keep a list of classes that were exhausted on the search for new // data members, initialize it with the class Construction. int cnt = 0; int super_cnt = -1; Vertex* vtx = new Vertex( new DemIdent( "Construction" ) ); Normal* constr = new Normal(); constr -> set_vertex( vtx ); TermRef* n_termRef = new LocalRef(); constr -> set_moduleRef( n_termRef ); Term_Comma_list* done = new Term_Comma_list( constr ); this -> gen_get_data_member( outFile, adjacencies, cnt, super_cnt, done ); outFile << " default: cerr << \"" << class_name << "::get_data_member. " << "Failed to get data member \"\n" << " << \"(invalid index \" << " << "index << \")\\n\";\n " << " exit( 1 );\n" << " }\n"; if ( number_of_parts == 0 ) { outFile << " return ( NULL );\n"; } outFile << "}\n\n"; number_of_parts = cnt; // generate method void C::set_data_member( int, Universal* ) outFile << "void " << class_name << "::set_data_member( int index, Universal* "; /* To get rid of the warning message 'fill not used' during compilation of generated files give variable name only for one or more parts. */ if ( number_of_parts ) { outFile << "fill"; } outFile << " )\n{\n" << " switch( index ) {\n"; // get all data members cnt = 0; super_cnt = -1; done = new Term_Comma_list( constr ); this -> gen_set_data_member( outFile, adjacencies, cnt, super_cnt, done ); outFile << " default: cerr << \"" << class_name << "::set_data_member: " << "Failed to set data member \"\n" << " << \"(invalid index \" << " << "index << \")\\n\";\n " << " exit( 1 );\n" << " }\n" << "}\n\n"; // generate method int C::number_of_parts() outFile << "int " << class_name << "::number_of_parts() const\n{\n return ( " << number_of_parts << " );\n}\n" << endl; // generate method int C::number_of_imm_parts() outFile << "int " << class_name << "::number_of_imm_parts() const\n{\n return ( " << number_of_imm_parts << " );\n}\n" << endl; DBG( cout << "OUT Adjacency::gen_data_member" << endl ); } /*------------------------------------------------------------------------- * Method: void gen_set_data_member * ( ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt ) * * Generates the 'switch part' for inherited data members in the generated * method void* C::set_data_member( int, Universal* ). This methods works * analogously to the countv_parts() method. *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::gen_set_data_member ( ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt, int& super_cnt, Term_Comma_list* done ) { DBG( cout << "IN Adjacency::gen_set_data_member" << endl ); this -> gen_imm_set_data_member( outFile, adjacencies, cnt, super_cnt ); // add to the current superclass member count if ( super_cnt < 0 ) super_cnt = 0; this -> count_imm_parts( super_cnt ); if ( inherits_from ) { inherits_from -> gen_set_data_member ( outFile, adjacencies, cnt, super_cnt, done ); } DBG( cout << "OUT Adjacency::gen_set_data_member" << endl ); } /* * term-comma_List ~ term { "," term } . */ void Term_Comma_list::gen_set_data_member ( ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt, int& super_cnt, Term_Comma_list* done ) { Term_list_iterator next_term( *this ); Term_ each_term; Adjacency* super; while ( each_term = next_term() ) { if ( ! done -> member( each_term, term_memberfunc ) ) { if ( ! each_term -> is_NonDemTerm() ) { super = each_term -> get_adjacency( adjacencies ); super -> gen_set_data_member ( outFile, adjacencies, cnt, super_cnt, done ); } done -> append( each_term ); } } } /*------------------------------------------------------------------------- * Method: void gen_imm_set_data_member * ( ofstream&, Adjacency_Nlist*, int&, int& ) * * Generates the 'switch-part' of the generated method Universal* C::set_ * data_member( int, Universal* ) for the immediate data members of an * inherited class. This method works analogously to the count_imm_parts() * method. *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::gen_imm_set_data_member ( ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt, int& super_cnt ) { ns -> gen_imm_set_data_member( outFile, adjacencies, cnt, super_cnt, this->get_class_name() ); } /* * neighbors : neighbors_wc | repetit_n | intermediate_ns *common* . */ void Neighbors::gen_imm_set_data_member ( ofstream& , Adjacency_Nlist*, int&, int&, char* ) { } /* * intermediate_ns : repetit | non_repetit *common* . */ void Intermediate_ns::gen_imm_set_data_member ( ofstream&, Adjacency_Nlist *, int&, int&, char * ) { } /* * non_repetit : instantiable | abstract * *common* < intermed_ns > int_part-List . */ void Non_repetit::gen_imm_set_data_member ( ofstream& outFile, Adjacency_Nlist*adjacencies, int& cnt, int& super_cnt, char* class_name ) { intermed_ns->gen_imm_set_data_member (outFile, adjacencies, cnt, super_cnt, class_name); } /* * int_part-List ~ { int_part } . */ void Int_part_List::gen_imm_set_data_member ( ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt, int& super_cnt, char* class_name ) /* * Since repetition classes don't inherit virtually from Universal, we * must distinguish between parts that are repetition classes and others. * Repetition classes use a normal castdown, the others must invoke the * explicit castdown function. This might change in the future. */ { Int_part_list_iterator next_part( *this ); Int_part_ each_part; while ( each_part = next_part() ) { outFile << " case " << cnt << " : "; if ( ! each_part -> is_NonDemTerm() ) { // regular Demeter data member if ( super_cnt < 0 ) { // accessing the actual immediate parts (no superclass) outFile << "this -> " << each_part -> get_var_name() << " = "; if ( MIFLAG ) { // castdown for MI // check if part is repetition class Adjacency *adj = each_part -> get_adjacency( adjacencies ); // adj might be NULL for terminal classes. if (adj != NULL && strcmp( adj->get_ns()->get_type(), "Repetit") == 0) { // repetition part: normal cast outFile << "(" << each_part -> get_class_name() << "*) fill ); "; } else { // non repetition part: castdown outFile << each_part -> get_class_name() << "::castdown(fill) ); "; } } else { // regular cast for SI outFile << "(" << each_part -> get_class_name() << "*) fill; "; } } else { // accessing data member of a superclass outFile << class_name << "::set_data_member( index - " << super_cnt << ", fill );"; } } else { // Non-Demeter term: set_data_member method not applicable outFile << "cerr << \"" << class_name << "::set_data_member: " << "Failed to set data member " << cnt << " \"\n" << " << \"(not of type Universal)\\n\";\n " << " exit( 1 ); "; } outFile << "break;\n"; cnt++; } // while } /*------------------------------------------------------------------------- * Method: void gen_get_data_member * (ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt, int& super_cnt) * * Generates the 'switch part' for inherited data members in the generated * method Universal *C::get_data_member( int ). This methods works analo- * gously to the count_parts() method. * 11/5/92: Note that for CppTerms and for external library terms a NULL * pointer has to be returned. *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::gen_get_data_member ( ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt, int& super_cnt, Term_Comma_list* done ) { DBG( cout << "IN Adjacency::gen_get_data_member" << endl ); this -> gen_imm_get_data_member( outFile, cnt, super_cnt ); // add to the current superclass member count if ( super_cnt < 0 ) super_cnt = 0; this -> count_imm_parts( super_cnt ); if ( inherits_from ) { inherits_from -> gen_get_data_member ( outFile, adjacencies, cnt, super_cnt, done ); } DBG( cout << "OUT Adjacency::gen_get_data_member" << endl ); } /* * term-comma_List ~ term { "," term } . */ void Term_Comma_list::gen_get_data_member ( ofstream& outFile, Adjacency_Nlist* adjacencies, int& cnt, int& super_cnt, Term_Comma_list* done ) { Term_list_iterator next_term( *this ); Term_ each_term; Adjacency* super; while ( each_term = next_term() ) { if ( ! done -> member( each_term, term_memberfunc ) ) { if ( ! each_term -> is_NonDemTerm() ) { super = each_term -> get_adjacency( adjacencies ); super -> gen_get_data_member ( outFile, adjacencies, cnt, super_cnt, done ); } done -> append( each_term ); } } } /*------------------------------------------------------------------------- * Method: void gen_imm_get_data_member * ( ofstream& outFile, int& cnt, int& super_cnt ) * * Generates the 'switch-part' of the generated method Universal* C::get_ * data_member( int ) for the immediate data members of an inherited class. * This method works analogously to the count_imm_parts() method. *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::gen_imm_get_data_member ( ofstream& outFile, int& cnt, int& super_cnt ) { ns -> gen_imm_get_data_member ( outFile, cnt, super_cnt, this -> get_class_name() ); } /* * neighbors : neighbors_wc | repetit_n | intermediate_ns *common* . */ void Neighbors::gen_imm_get_data_member( ofstream&, int&, int&, char* ) { } /* * intermediate_ns : repetit | non_repetit *common* . */ void Intermediate_ns::gen_imm_get_data_member ( ofstream&, int&, int&, char* ) { } /* * non_repetit : instantiable | abstract * *common* < intermed_ns > int_part-List . */ void Non_repetit::gen_imm_get_data_member ( ofstream& outFile, int& cnt, int& super_cnt, char* class_name ) { intermed_ns -> gen_imm_get_data_member ( outFile, cnt, super_cnt, class_name ); } /* * int_part-List ~ { int_part } . */ void Int_part_List::gen_imm_get_data_member ( ofstream& outFile, int& cnt, int& super_cnt, char* class_name ) { Int_part_list_iterator next_part( *this ); Int_part_ each_part; while ( each_part = next_part() ) { outFile << " case " << cnt << " : return ( "; // check whether to return the requested part or NULL // NULL is returned for all CppTerms and external library terms if ( ! each_part -> is_NonDemTerm() ) { // regular Demeter data member if ( super_cnt < 0 ) { // accessing the actual immediate parts (no superclass) outFile << "(Universal*) this -> " << each_part -> get_var_name(); } else { // accessing data member of a superclass outFile << "(Universal*) " << class_name << "::get_data_member( " << cnt - super_cnt << " )"; } } else { // Non-Demeter term: get_data_member method not applicable outFile << "NULL"; } outFile << " );\n"; cnt++; } } int Int_part::is_NonDemTerm() { return ( labeled_int_part->is_NonDemTerm() ); } int Labeled::is_NonDemTerm() { return ( get_vertex()->is_NonDemTerm() ); } int Term::is_NonDemTerm() { // default for CppTerm return ( 1 ); } int Normal::is_NonDemTerm() { return ( get_moduleRef() -> is_NonDemTerm() ); } int TermRef::is_NonDemTerm() { // return default for LocalRef and CompRef return ( 0 ); } int LibRef::is_NonDemTerm() { return ( 1 ); } /*------------------------------------------------------------------------- * Method: * void count_parts( int& no_of_parts, Adjacency_Nlist* adjacencies ) * * Counts the number of parts of an Adjacency (including those inherited). * This is done by first counting the number of immediate parts in the * adjacency at hand. Then all the parts of the inherited classes are * added. This is done recursively going up the whole inheritance hier- * archy. * *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ /* void Adjacency::count_parts ( int& no_of_parts, Adjacency_Nlist* adjacencies ) { this -> count_imm_parts( no_of_parts ); if ( inherits_from ) { inherits_from -> count_parts( no_of_parts, adjacencies ); } } */ /* * term-comma_List ~ term { "," term } . */ /* void Term_Comma_list::count_parts ( int& no_of_parts, Adjacency_Nlist* adjacencies ) { Term_list_iterator next_term( *this ); Term_ each_term; while ( each_term = next_term() ) { if ( strcmp( each_term -> get_class_name(), "Construction" ) != 0 ) { each_term -> get_adjacency( adjacencies ) -> count_parts( no_of_parts, adjacencies ); } } } */ /*------------------------------------------------------------------------- * Method: void count_imm_parts( int& no_of_parts ) * * Counts only the number of immediate parts of an adjacency (without those * inherited). *-----------------------------------------------------------------------*/ /* * adjacency = < source > vertex < ns > neighbors * [ "*inherits_from*" < inherits_from > term-comma_List ] "." . */ void Adjacency::count_imm_parts( int& no_of_parts ) { ns -> count_imm_parts( no_of_parts ); } /* * neighbors : neighbors_wc | repetit_n | intermediate_ns *common* . */ void Neighbors::count_imm_parts( int& ) { } /* * intermediate_ns : repetit | non_repetit *common* . */ void Intermediate_ns::count_imm_parts( int& ) { } /* * non_repetit : instantiable | abstract * *common* < intermed_ns > int_part-List . */ void Non_repetit::count_imm_parts( int& no_of_parts ) { no_of_parts += intermed_ns -> list_length(); } Adjacency* Int_part::get_adjacency( Adjacency_Nlist* adjacencies ) { // Labeled return ( labeled_int_part->get_adjacency( adjacencies ) ); } Adjacency* Required_int_part::get_adjacency( Adjacency_Nlist* adjacencies ) { return ( this->Int_part::get_adjacency( adjacencies ) ); } Adjacency* Optional_int_part::get_adjacency( Adjacency_Nlist* adjacencies ) { return ( this->Int_part::get_adjacency( adjacencies ) ); } Adjacency* Opt_labeled_term::get_adjacency( Adjacency_Nlist* adjacencies ) { // Term return ( vertex->get_adjacency( adjacencies ) ); } Adjacency* Labeled::get_adjacency( Adjacency_Nlist* adjacencies ) { return ( this->Opt_labeled_term::get_adjacency( adjacencies ) ); }