[Update 27/04/2007, this post has been overdue for almost two weeks now.]
As I promised that I’ll be discussing Function and its descendants in this post, here are the tiniest little details about them. A Function represents a free standing, translation unit level function. It has a name, a return type, a set of parameters, an optional exception specification, a possible function level try block, and most importantly, a set of statements. These details also apply to all of its descendants, with a few exceptions. A function can be inline and can have template parameters in its declaration.
Public interface for a function is fairly simple and most functions are either get/set style or return a reference/pointer to some internal representation detail. The real fun resides with the protected interface to the class. It begins with the call to writetext. This function first writes out all the template parameters if any using writetemplateattributes. Then, if the function is declared inline, inline is written to the output stream. Then, if there is a return type specified, first its declarator is written followed by its declarator specifier (omitting the name of variable). Next, we write the name of function. This function is virtual because constructors and destructors do not have separate names. After writing the name, we move on to the parameter list and write it using writeparameters. This function calls writeasparameters for each parameter in VariableDeclaration collection. Now, it is time to write exception specifications if any using writeexceptionspecs. This function first checks whether the target compiler supports exceptions specifications and if the result is false does nothing, otherwise, writes every type name in the given list. Next, we write try for function level try block after checking the result of FunctionTryBlock. This function returns true only in the case if the target compiler supports function level try blocks and this function has associated catch clauses. With everything done, it is time to write the body of function using writebody. writebody iterates through all the statements and writes them one at a time. Finally, if FunctionTryBlock returned true earlier, we write the associated catch clauses.
This discussion left one important piece of functionality away. The need to write a function declaration in header files and in class definitions. We do this with the help of writedeclaration which calls the virtual function declaration. This function writes all the template parameter, the return type if any, declarations of all parameters and exception specifications if any.
Next important class is the MemberFunction. A MemberFunction represents a class member function. A separate class is necessary because it has a set of attributes like static, virtual, const, volatile, pure and accessibility. Some of these are mutually exclusive or imply others, like a static function cannot be virtual, const or volatile; a pure function implies virtual; virtual excludes any template parameters. All the dirty work is handled in get/set functions for its attributes and writetext works almost like that for a function, with the additional work of writing template parameters of its parent class and writing attributes like static, virtual, const, volatile and = 0 where applicable. declaration also works similarly and inserts additional information where necessary.
Constructor represents a class’s constructor. It has two additional attributes. Get/set functions for explicit and a list for constructor initializers. writetext does the extra work of writing explicit before inline if necessary and writing constructor initializers right before writing the body of constructor. declaration changes to accommodate the facts that a constructor has no return type and has the same name as its parent class.
A Destructor has two additional attributes apart from those of Function for representing its virtual and pure properties. Its writetext is very simple and only writes the template parameters of parent class, name, exception specifications, function level try block and body of destructor. declaration is even simpler, it write template parameters for parent class, name and exception specifications.
Finally, we consider syntactic sugar, Operator and MemberOperator. An Operator is just a function with the changes that it does not have a name; its name returns the textual representation of the operator it overloads and has one additional attribute that returns the operator type. It does not override writetext or declaration because overriding Name does the job. A MemberOperator derives from Operator and adds additional attributes just like MemberFunction does to Function, with the noted exception that a member operator cannot be declared static. writetext and declaration for MemberOperator work just like for Operator except that it adds the template parameters of parent class before anything else.
Type‘s family is already squeaking in my ears to go out to public.