Skip to content

A Walkthrough the Code

Elliot Chance edited this page May 5, 2017 · 4 revisions

This wiki page is a starting point for anyone that is interested in understanding how c2go works internally or are interested in learning the code base to work on issues.

This page is still a work in progress.

Overview

The basic process is this:

  1. The clang program preprocesses the C input file and produces a temporary file, /tmp/pp.c. This file contains a lot more source code because all the of the #include directives have been evaluated.
  2. The clang program is used again to parse the pp.c file and produce an AST. This is the coloured output you will see below.
  3. The clang output (which is text) is converted by the ast package into a real AST.
  4. The transpiler package converts the AST into Go's internal AST.
  5. The Go AST is rendered into Go code.

The Clang AST

The clang program parses C and produces text that represents the internal clang AST, here is an example of the output:

clang output

This text (once the colours have been removed) is parsed by ast.Parse() to produce an object that looks similar to:

*ast.FunctionDecl {
    Name: "foo"
    Type: "void (struct S *)"
    Children: []*ast.Node{
        *ast.ParmVarDecl{
            Used: true
            Name: "s"
            Type: "struct S *"
        }
        *ast.CompoundStmt{
            Children: []*ast.Node{
                *ast.CallExpr{
                    // ...
                }
            }
        }
    }
}

I say similar because there are lots of other attributes extract that are not shown to keep the output short.

Transpiling the AST

Transpiling (an amalgamation of the words, translate and compile) is the process of translating some course code to some other source code. This can be done in all sorts of different ways by we iterate through the AST structure and produce a new Go AST.

The transpiling is done in the transpiler package. When we pass in the AST in the example above to transpiler.TranspileAST() it will return a new Go AST that looks similar:

*ast.FuncDecl{
    Name: "foo"
    Type: *ast.FuncType{
        Params: []*goast.Field{
            *ast.Field{
                Names: []*ast.Ident{"s"}
                Type:  "struct S *"
            }
        }
        Body: *ast.CompoundStmt{
            // ...
        }
}

One ambiguous thing is that both packages are called "ast". When using the Go AST it is aliased to "goast".

Packages

Here is a short description of where you will find things:

  • ast contains the code for parsing the clang AST output and building the AST. Each file in the package represents a different AST node and has an associated test file with examples.
  • transpiler contains methods for transpiling the ast nodes into the Go AST. This is where most of the code is currently located.
  • noarch, darwin and linux contains Go implementations of low-level functions for each system. These functions are usually provided by cstdlib. noarch contains that are required on multiple system or are the same implementation on multiple systems.
  • util contains helper functions and other common utilities that is shared by the other packages.
Clone this wiki locally