/**************************************************************************
* 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 ) );
}