How does Cling (C++ Interpreter) work?

Kaustubh Narkhede
4 min readApr 19, 2021

I learned Python as my first language, and have been learning C++ for a couple of months now, and the major thing I miss from Python is the command-line interpreter, may it be IPython or the built-in one, you can just test the code on the fly.

On the contrary in C++, I have to create a new file, type all the starter code, (even more ordeal in Visual Studio) …. then I forget what I was going to do! So frustrating right?

I am loving the language, but when I am working on a project, and I have to test whether the way I am thinking a thing would work actually does, I went like… Ughhhh!!! Not again!! For the most of time, I just created a spare experimental project solution in Visual Studio to ease my life.

Until….

I found out about Cling.

This article gives an overview of cling. For installation instructions see my next post.

What is Cling?

With cling, you can prototype before deploying the code into your original application.

It is a core ingredient in the ROOT project which is an open-source framework for data analysis, persistence, and graphics visualization. Born at CERN, at the heart of the research on high-energy physics.

No wonder it has been developed by a CERN LHC. A buggy line would result in damage worth millions and may prove fatal as well!

It is a successor to CINT (20-year-old C++ interpreter).

Cling is an interactive C++ interpreter, built on top of Clang and LLVM compiler infrastructure. Cling realizes the read-eval-print loop (REPL) concept, to leverage rapid application development and encourage explorative learning.

Now a C++ REPL may sound strange to a lot of folks, after all, C++ is a compiled language.

However, any programming language can be implemented as a compiler or as an interpreter and Cling happens to be an interactive C++ interpreter based on LLVM and Clang.

It maps the concept of the interpreter to the compiler. So, it is can be thought of as a Just-In-Time (JIT) Compiler.

How?

The idea of a translation unit is given a new meaning here,

In C++ compiler sees a translation unit as the full input it ever sees, but this cannot be in Cling because, the AST (Abstract Syntax Tree) will grow, so the code generation be should after each input.

(An abstract syntax tree (AST), or just syntax tree, is a tree representation of the abstract syntactic structure of source code written in a programming language. Each node of the tree denotes a construct occurring in the source code. The syntax is “abstract” in the sense that it does not represent every detail appearing in the real syntax, but rather just the structural or content-related details. Read more on Wikipedia)

This may not be obvious, because there is no way you can write C++ code in a global space.

For example:

double a = 5.5; 
log(a);

cannot go in the global space, it needs a wrapper around it like;

void wrapper() 
{
double a = 5.5;
log(a);
}

So, Cling first wraps it, so that clang can parse it, and tell us which part is an expression versus, which part is a declaration.

Here, for instance,

double a = 5.5;

is a declaration, and

log(a);

is an expression.

When it’s a declaration, cling extracts the declaration and moves it to the global scope. It is important because the user should be able to reference the declaration anytime. (This happens at the AST level).

What we are left with is

void wrapper()
{
log(a);
}

calling this function as

wrapper();

gives us the desired output.

(Cling prints the output, if you omit the semicolon.)

(C++ is a statically typed language, hence it also becomes essential to stores the target info (ex. datatype) and ABI for use afterward)

Be cautious though, when you write the illegal code here, the whole thing (all the variables, functions everything) goes away (~cling() destructor is called), because it’s the most obvious thing to do!

When you give it an expression that expects input parameters not already defined, cling injects it into the current scope, while its compilation is delayed until the run time. This implies that Compiler is used rather as a service.

Cling is also ABI compatible.

(An application binary interface (ABI) is an interface between two binary program modules. Often, one of these modules is a library or operating system facility, and the other is a program that is being run by a user.)

This means that you can use external libraries, like:

#include <iostream>std::cout << Hello Medium << std::endl;

If you want a more thorough explanation, refer: https://blog.llvm.org/posts/2020-11-30-interactive-cpp-with-cling/

A quick demo video to appreciate the beauty of cling:

--

--

Kaustubh Narkhede

Documenting my exploration of the world of Computer Science…. GitHub: github.com/kaustubh138