#ifndef cmm_h #define cmm_h #include "lexer.h" #include "parser.h" #include #ifdef __GNUC__ std::stringstream* MakeStringStream(); /* to get round internal compiler errors with gcc. */ #endif namespace cmm { /* This namespace contains two structs that are specific to Cmm's operation. secondpass_info and ThirdPassInfo contains similar information - virtual functions and implementations of virtual functions. However, there are differences, because the two types are generated from different files - secondpass_info from .cmm files with `cmm -c' and ThirdPassInfo from .cmmi files with `cmm -l'. The representation of class hierachies is different because they are stored in a condensed form within .cmmi files, compared to .cmm source. Also, ThirdPassInfo contains a list of virtual functions, each with a list of compatiable implementations, whereas secondpass_info (currently) contains separate lists of virtual functions and implementation functions. There's probably scope for making these two classes more similar. */ struct secondpass_info; struct parameter_t /* The inheritance information for a virtual parameter. Base class comes first, followed by the more derived classes. */ { parameter_t() : is_virtual( false), virtual_classname( NULL), derivation() {} typedef std::deque< const parser::class_t*> derivation_t; bool is_virtual; bool is_templatespec_virtual; parser::name_t* virtual_classname; // can be NULL if not a virtual param. // is `base' in `void foo( virtual base&); // is also `base' in `void foo( shared_ptr< virtual base>). // Otherwise NULL if not a virtual parameter (but is_virtual...?). derivation_t derivation; parser::declarator_names_t* declnames; // the original parameter declaration. }; struct parameters_t : std::vector< parameter_t*> { parameters_t( parser::declarator_names_t* fn, const secondpass_info& secondpassinfo); }; struct implementation_t; struct multimethod_t { typedef std::vector< implementation_t*> implementations_t; parser::template_t* templat; parser::declarator_names_t* fn; parser::declarator_names_t* getimplfn; parameters_t parameters; implementations_t implementations; const std::string* filename; /* where the virtual function prototype was found. Not actually used for anything...*/ parser::node_t* original_node; /* used to identify where this was seen in original source.*/ multimethod_t( const secondpass_info& secondpassinfo, parser::template_t* templat0, parser::declarator_names_t* fn0, const std::string* filename0, parser::node_t* original_node0); ~multimethod_t(); }; struct implementation_t /* info about an implementation of a virtual function Note that functions are represented as parser::declarator_names_t. This makes the code rather messy - have to assert that there the declarator_names_t has just one declarator_terminator_t, and call is_simple_function() to get the function_t*. Should really make a bit more use of static typing - e.g. have a new class that contains a pointer to the declarator_names_t, and also has explicit info about the function_t* etc.*/ { implementation_t(); std::string filename; parser::template_t* templat; parser::declarator_names_t* implfn; // this implementation parser::declarator_names_t* implcall; // calls implfn after static_casting params. parser::declarator_names_t* implmatch; // takes virtual params, and tests them with dynamic_cast. parser::declarator_names_t* implmatch_minuss; // takes array of void*'s for virtual params and tests with dynamic_cast. parameters_t* parameters; // info on derivedness of each virtual parameter for this impl. multimethod_t* multimethod; // pointer to info about the original virtual fn. }; struct class2_t { parser::class_t* clas; parser::template_t* templat; class2_t( parser::class_t* c, parser::template_t* t) : clas( c), templat( t) {} }; struct secondpass_info /* Contains info about all virtual functions and implementations in a compilation unit. This generated by `cmm -c ...', by looking at the parser tree generated from parsing a .cmm file. */ { explicit secondpass_info( const parser::compilation_unit_t& compunit, const char* outfilename, bool generate_small_ints); /* outfilename is the name of the file that translated source will be output to by `OutputTranslatedSource()'. It is also included in the output generated by OutputImplDetails, so that `cmm -l' knows which files to append dispatch code to. if_t generate_small_ints is true, all classes with vtables will have an inline `virtual int cmm_get_small_integer() const;' method added.*/ void AddItems( const std::vector< parser::node_t*>& items); /* Used internally by constructor. Extracts information about class names and functions from `items'. */ void OutputImplDetails( std::ostream& out) const; /* Outputs information to the cmmi file 'out', for use my cmm -l. Contains enough information for generation of virtual dispatch functions. This information is read by ThirdPassInfo::AddFns() when `cmm -l' is run. */ void OutputTranslatedSource( bool no_hash_lines, parser::exceptions_translation exceptiontranslation, bool cmm_minus_s, bool caller_dispatch, const std::string& block_text, const std::string& pre_text) const; /* Outputs source with all match/call functions for any implementations found. if 'no_hash_lines' is true, the output contains no hash lines; useful for debugging the auto-generated C++ code. This is used by cmm -c. if_t cmm_minus_s is true, also outputs code to register each implementation dynamically and an inline implementation of the virtual function. This code requires the functions in cmm's dispatch.cpp file to be available at link time. */ void output( std::ostream& stream) const; /* For debugging only. */ typedef std::vector< class2_t*> classes_t; typedef std::vector< parser::typedef_t*> typedefs_t; typedef std::vector< multimethod_t*> multimethods_t; typedef std::vector< const implementation_t*> implementations_t; typedef std::vector< parser::declarator_names_t*> memberrecursives_t; const parser::compilation_unit_t& compunit; const std::string outfilename; // So that we generate translated source to same file as we sepcify in cmm info file. classes_t classes; typedefs_t typedefs; multimethods_t multimethods; implementations_t implementations; memberrecursives_t memberrecursives; const bool generate_small_ints; }; struct ThirdPassInfo /* This is generated from a .cmmi file by `cmm -l ...'. */ { struct Extra /* Represents the extra configuration choices accepted by cmm. */ { Extra(); std::string mapinclude; // include file that contains the map class std::string maptype; // the name of the map class. std::string profileinclude; std::string profiletype; std::string arrayinclude; std::string arraytype; bool no_exceptions_in_generated_code; }; ThirdPassInfo( const Extra& extra); void AddFns( std::istream& in); // Reads in a cmmi file. Should maybe in constructor. void output( std::ostream& out) const; // Debugging only. struct VirtFn { struct Impl { struct Param { Param() : classnames() {} typedef std::vector< parser::name_t*> classnames_t; classnames_t classnames; }; Impl() : filename(), params(), implmatch(), implcall() {} std::string filename; typedef std::vector< Param*> params_t; params_t params; // info on derivedness of each virtual parameter. parser::declarator_names_t* implmatch; // the impmatch function parser::declarator_names_t* implcall; // the implcall function }; VirtFn() : virtfn( NULL), filename( NULL), impls() {} typedef std::vector< Impl*> impls_t; parser::declarator_names_t* virtfn; parser::string_t* filename; impls_t impls; }; Extra extra; typedef std::vector< VirtFn*> virtfns_t; virtfns_t virtfns; }; parser::declarator_names_t* MakeLookupFn( ThirdPassInfo::VirtFn* virtfn, const ThirdPassInfo& thirdpassinfo); /* creates a lookup function for the specified virtual function. This dispatch function knows about all of the available implementation functions, and some parts of the code depend on the parameters in thirdpassinfo.extra - e.g. the type of map to use to cache dynamic dispatch lookups. */ parser::declarator_names_t* MakeDispatchFn( ThirdPassInfo::VirtFn* virtfn, const ThirdPassInfo& thirdpassinfo); /* creates a dispatch function for the specified virtual function. This dispatch function knows about all of the available implementation functions, and some parts of the code depend on the parameters in thirdpassinfo.extra - e.g. the type of map to use to cache dynamic dispatch lookups. */ void OutputPreDispatchCode( std::ostream& out, ThirdPassInfo::VirtFn& virtfn, const ThirdPassInfo& thirdpassinfo); /* Generates the #include statements needed by the dispatch function generated by MakeDispatchFn above. */ } #endif