Bug Vanquisher

9 June 2007

Runtime Code Generation in C++ 6

Filed under: C++ — Tanveer Badar @ 3:38 PM

As I said last time, no discussion of a language is complete without statements and expressions. We talked about expressions in CppCodeProvider last time. Today’s topic is statements. Everything in C++ is a statement. You declared a function or a variable, it is a declaration statement; define a class, it is another declaration statement; define a function, another declaration statement; write a loop, iteration statement; use if-else or switch, conditional statement; perform any type of jumping by goto, return, break or continue all are jump-statements; declare variable on a for-loop, a for-loop init statement; label something or write case or default inside a switch, labeled statement; surround a piece of code with braces, compound statement; use a semi-colon after an expression, expression-statement!

In short everything is a statement in C++. There is simply no escaping this fact of life. My life is complicated by the compound statement thing. Since anything can be a statement and come after anything in either braces or otherwise, every class to represent a type of statement must derive from same base class, Statement.

First there is an ExpressionStatement, which takes an Expression as an argument and turns it into a Statement. There is a UsingStatement, which declares an identifier to be visible in another scope. We are used to jumping all over the place, all our lives. JumpStatement captures the essence of jumping. It takes either a string to generate a goto, a member of JumpType except goto, or an optional expression to generate a return. It is illegal to specify Goto as an argument to second constructor because a goto requires a label to jump to. The expression passed to the third constructor must not be null because for a simple return with no value you should pass JumpType::Return to the second constructor. To accompany the goto of JumpStatement, we have a LabelStatement which takes a string and another statement and applies that string as a label to that statement.

We have discussed all the single statement constructs for statements. It is time to move on to statement blocks. It is legal to have a single statement block, but it will be surrounded by { } and introduces a new lexical scope. For compound statement, you use StatementBlock. StatementBlock can be instantiated with a collection of statements which will be part of it or default initialized. All statements which are part of one StatementBlock can be accessed through Statements( ). This class is the base class for almost every other kind of statements.

A catch block is essentially a compound statement with one optional exception variable declared and initialized before the scope is entered by execution. CatchClause represents this structure in code graph. It optionallly takes a VariableDeclaration or default initialized if this catch block is a catch-all type. The exception variable is accessible through CatchType and since it inherits from StatementBlock all statements are also accessible.

We use CatchClause to build higher level construct, namely try-catch block. A try-catch block has a body of statements surrounded by try and a list of catch clauses which catch exceptions thrown by try block. TryCatchCaluse is always default initialized and you add statements to try block with Statements( ) and catch blocks through CatchClauses( ). Both of these functions return an appropriate collection where you can call push_back to add new items.

A case statement also inherits from StatementBlock. It takes an optional bool parameter to indicate if case block should begin in a new lexical scope because it contains variable declarations. If you provide a PrimitiveExpression to Instantiate it becomes the label for case, otherwise, a default is generated. Although it is illegal to have more than one default or same case in a switch statement, these checks are more high level than any code dom. Therefore, it is the responsibility of client to ensure it does not happen, otherwise, deal with it when the compiler whines on the source code :). Also, there is no check to see if the PrimitiveExpression is really a compile time integral constant or not, you will have to face your compiler if you do contrariwise.

Similar to CatchClause, we use Case to build a higher level construct, SwitchStatement. A switch is essentially an expression which is evaluated at runtime and a bunch of case blocks crammed together in one lexical scope. You construct a SwitchStatement by providing an Expression and adding case blocks through Cases( ). An alternative to switch is the if-else clause. Sometimes there is no option other than if. e.g., if want to test for a range, want to check for a floating-point value, value is not a compile time constant etc. If-else clause is used as ConditionClause. You provide it with only the expression which is checked in if( ). Statements which will be part of if block are accessed through Statements( ), those which will be part of else block are accessed as a StatementBlock with Else( ). Condition can be retrieved with Condition( ). Special treatment for else block is necessary only because it is not possible to inherit from StatementBlcok twice directly. Therefore, else block is exposed as a StatemntBlock object and statements in if block are inherited through Statements( ).

All loops are clumped in the base class of IterationClause which inherits from StatementBlock. Since all statements of loop body are already accessible through Statements( ), IterationClause only introduces a Condition( ) to access loop condition. The class is abstract as there is no way to realize a loop without telling whether it is a for, while or do-while loop. A ForLoop specializes IterationClause with two additional expressions for ‘for-initialization statement’ and increment expression. If none of these three expression is given, an infinite for loop is generated. WhileLoop and DoWhileLoop specialize IterationClause to generate different forms of loop with a body and condition only.

1 Comment »

  1. […] Of course, if you are wondering what the hell CPPCodeProvider is, here are some links which explain it in much more details: part 1, part 2, part 3, part 4, part 5 and part 6. […]

    Pingback by Major Changes in CPPCodeProvider « Bug Vanquisher — 4 November 2007 @ 7:03 PM

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

%d bloggers like this: