Getting started...

Architecture

Here the involved modules in this tutorial are two:

CSharpToCppConverterVisitor: Located in NRefactory/ICSharpCode.NRefactory.Cpp/Visitors. In this module we will develop the conversions of the tokens from .NET syntax to C++ syntax.

Located in NRefactory/ICSharpCode.NRefactory.Cpp/Visitors. In this module we will develop the conversions of the tokens from .NET syntax to C++ syntax. CppOutputVisitor: Located in NRefactory/ICSharpCode.NRefactory.Cpp/OutputVisitor. In this module we will implement how the tokens (already converted) are ordered and writen to the output.

For example, if we have to convert the statement byte[] b = new byte[10];

CSharpToCppConverterVisitor will make these conversions byte -> char Array specifier [ ] -> * (pointer declaration) And again new byte[10] -> new char[10]

will make these conversions CppOutputVisitor will output the tokens before in this order: char* b = new char[10];

AST flow

The flow of the AST transformations is processed like a tree pattern. Each node denotes a construction in the source code. The major part of the nodes are composed by other nodes which represent more specific code. As a simplified example, a node representing a = b + c, is a combination of:

A node representing the assignation of a variable a = something.

A node representing the sum of two elements: b + c.

Identify the transformation

Every transformation has to be identified inside the AST tree. We have to specify which node we want to translate (i.e. IfElseStatement node). In this tutorial we will see all the process of how to implement a simple transformation.

The code we will transform in this tutorial is a .NET feature, the "as" casting: Person p = myObject as Person;

In fact, the node we will transform is "myObject as Person" which we can identify that is an "As Expression" node.

We have to provide a new feature in C++ that is not available in the standard library. The new feature will be in charge of cast an object to another object. For maintaining the readability of the code, we propose implement a feature in the AlterNative Library for providing easy "as casting" in c++, for example: Person* p = as_cast<Person*>(myObject);

In other words, we have to convert an "As Expression" node into a "Call to Method Expression" node.

Transform it

We have to locate where is processed the "As Expression" node in order to translate it to a "Call to Method Expression" pointing to the method as_cast (that later we will implement in the AlterNative Library). These nodes are called in the AST "AsExpression" and "InvocationExpression". We have to find the method in charge of processing this node:

AstNode CSharp.IAstVisitor .VisitAsExpression(CSharp.AsExpression asExpression, object data) { //Here the node should be processed throw new NotImplementedException("As Expression is not implemented"); }

The process of our transformation is easy, we have to create an InvocationExpression node and fill it with the correct elements from AsExpression node.

AstNode CSharp.IAstVisitor .VisitAsExpression(CSharp.AsExpression asExpression, object data) { InvocationExpression invExpr = new InvocationExpression(); IdentifierExpression mref = new IdentifierExpression(); mref.TypeArguments.Add((AstType)asExpression.Type.AcceptVisitor(this, data)); mref.Identifier = "as_cast"; invExpr.Arguments.Add((Expression)asExpression.Expression.AcceptVisitor(this, data)); invExpr.Target = mref; return EndNode(asExpression, invExpr); }

The code above is a process that we call AST transformation. These AST transformations allows AlterNative to perform its work. In this tutorial, the transformation we have made can be described with this AST transformation:

If we assume that the nodes InvocationExpression and IdentifierExpression are implemented, it is not necessary to edit the module CppOutputVisitor because there is no new node created, and the nodes participating in this transformation already have been implemented and will output a well-formed C++ code. You may want to check these nodes in the CppOutputVisitor only for get familiarize with the code

Library feature

Now we have to implement the method as_cast (object) that we have supposed to be implemented in the library. This point is very important because is the code that makes the output source code compile. In this case the feature is simple and it is implemented with the "dynamic_cast" standard feature of C++11.

/* Method for C# feature as cast */ template < class T, class U > T as_cast(U u) { return dynamic_cast< T >(u); };

This feature supports a standard feature of C#, so we will implement it in the file System/support/asis.h which will be loaded always in our programs.