C++ has a new standard called C++0x (Wikipedia, Bjarne Stroustrup) that includes many interesting features such as Lambda, For Each, List Initialization ... Those features are so powerful that they allow to write C++ as if it was Javascript.

The goal of this project is to transform C++ into Javascript. We want to be able to copy & paste Javascript into C++ and be able to run it. While this is not 100% feasible, the result is quite amazing.

This is only a prototype. In about 600 lines of code we manage to make the core of the Javascript language.

You can view the source and compile examples at the JSPP Github Repository

JSON

The Javascript Object notation can be emulated thanks to C++0x initialization lists and a bit of operator overload hackery. _ has an operator [] that returns a KeyValue object, that has an operator = overload that fills both keys and values. For each value of the initialization listL If that's an objet, it is treated like an Array (add one to the lenght and use the length as key). If that's a KeyValue , both key and value are set.

There is an ambiguity with nested initialization lists, we use _() to cast the list into an Object. It is probably possible to fix it.

C++ var json = { _ [ "number" ] = 42 , _ [ "string" ] = "vjeux" , _ [ "array" ] = { 1 , 2 , "three" } , _ [ "nested" ] = _ ( { _ [ "first" ] = 1 } ) } ; std :: cout < < json ; // {array: [1, 2, three], nested: {first: 1}, // number: 42, string: vjeux} var json = { _["number"] = 42, _["string"] = "vjeux", _["array"] = {1, 2, "three"}, _["nested"] = _({ _["first"] = 1 }) }; std::cout < < json; // {array: [1, 2, three], nested: {first: 1}, // number: 42, string: vjeux} Javascript var json = { "number" : 42 , "string" : "vjeux" , "array" : [ 1 , 2 , "three" ] , "nested" : { "first" : 1 } } ; console. log ( json ) ; // {number: 42, string: 'vjeux', // array: [1, 2, three], nested: {first: 1}} var json = { "number": 42, "string": "vjeux", "array": [1, 2, "three"], "nested": { "first": 1 } }; console.log(json); // {number: 42, string: 'vjeux', // array: [1, 2, three], nested: {first: 1}}

Function

C++0x added lambda to the language with the following syntax: [capture] (arguments) -> returnType { body } . function is a macro that transforms function (var i) into [=] (Object This, Object arguments, var i) -> Object . This allows to use the Javascript syntax and let us sneakily add the this and arguments magic variables.

C++ is strongly typed and even lambdas have types. We can overload the Object constructor on

lambda arity and have a typed container for each one. Then, we overload the () operator that will call the stored lambda. We we carefully add undefined values for unspecified arguments and fill the This and arguments variables.

In Javascript, when a function does not return a value, it returns undefined. Sadly, we cannot have a default return value in C++, you have to write it yourself.

Since everything must be typed in C++, we have to add var before the argument name.

C++ var Utils = { _ [ "map" ] = function ( var array , var func ) { for ( var i = 0 ; i < array [ "length" ] ; ++ i ) { array [ i ] = func ( i , array [ i ] ) ; } return undefined ; } } ; var a = { "a" , "b" , "c" } ; std :: cout << a ; // [a, b, c] Utils [ "map" ] ( a , function ( var key , var value ) { return "(" + key + ":" + value + ")" ; } ) ; std :: cout << a ; // [(0:a), (1:b), (2:c)] var Utils = { _["map"] = function (var array, var func) { for (var i = 0; i < array["length"]; ++i) { array[i] = func(i, array[i]); } return undefined; } }; var a = {"a", "b", "c"}; std::cout << a; // [a, b, c] Utils["map"](a, function (var key, var value) { return "(" + key + ":" + value + ")"; }); std::cout << a; // [(0:a), (1:b), (2:c)] Javascript var Utils = { "map" : function ( array , func ) { for ( var i = 0 ; i < array [ "length" ] ; ++ i ) { array [ i ] = func ( i , array [ i ] ) ; } } } ; var a = [ "a" , "b" , "c" ] ; console. log ( a ) ; // [a, b, c] Utils [ "map" ] ( a , function ( key , value ) { return "(" + key + ":" + value + ")" ; } ) ; console. log ( a ) ; // [(0:a), (1:b), (2:c)] var Utils = { "map": function (array, func) { for (var i = 0; i < array["length"]; ++i) { array[i] = func(i, array[i]); } } }; var a = ["a", "b", "c"]; console.log(a); // [a, b, c] Utils["map"](a, function (key, value) { return "(" + key + ":" + value + ")"; }); console.log(a); // [(0:a), (1:b), (2:c)]

Closure

There are two ways to capture variables with lambda in C++: either by reference or by value. What we would like is to capture by reference in order for all the variables to be bound to the same object. However, when the initial variable gets out of scope it is destroyed, and any attempt to read it results in a Segmentation Fault!

Instead, we have to capture it by value. It means that a new object is created for each lambda capturing the variable. Our objects are manipulated by reference, meaning that assigning a new value to the object will just update it and not all the other copies. We introduce a new assignement operator obj |= value that updates all the copies.

C++ var container = function ( var data ) { var secret = data ; return { _ [ "set" ] = function ( var x ) { secret |= x ; return undefined ; } , _ [ "get" ] = function ( ) { return secret ; } } ; } ; var a = container ( "secret-a" ) ; var b = container ( "secret-b" ) ; a [ "set" ] ( "override-a" ) ; std :: cout < < a [ "get" ] ( ) ; // override-a std :: cout << b [ "get" ] ( ) ; // secret-b var container = function (var data) { var secret = data; return { _["set"] = function (var x) { secret |= x; return undefined; }, _["get"] = function () { return secret; } }; }; var a = container("secret-a"); var b = container("secret-b"); a["set"]("override-a"); std::cout < < a["get"](); // override-a std::cout << b["get"](); // secret-b Javascript var container = function ( data ) { var secret = data ; return { set : function ( x ) { secret = x ; } , get : function ( ) { return secret ; } } ; } ; var a = container ( "secret-a" ) ; var b = container ( "secret-b" ) ; a. set ( "override-a" ) ; console. log ( a. get ( ) ) ; // override-a console. log ( b. get ( ) ) ; // secret-b var container = function (data) { var secret = data; return { set: function (x) { secret = x; }, get: function () { return secret; } }; }; var a = container("secret-a"); var b = container("secret-b"); a.set("override-a"); console.log(a.get()); // override-a console.log(b.get()); // secret-b

This

There are four ways to set the this value:

Function call : foo() . this is set to the global object. As this is not a proper way to do things, I set it to undefined.

: . is set to the global object. As this is not a proper way to do things, I set it to undefined. Method call : object.foo() . this is set to object .

: . is set to . Constructor : new foo() . foo is called with a new instance of this .

: . is called with a new instance of . Explicit: foo.call(this, arguments...) . We explicitely set the this value.

All four ways are implemented in jspp but in a different way than Javascript. In Javascript, the language knows the construction and therefore can deduce what this is going to be. In C++, on the other hand, have a local view of what is going on. We have to develop another strategy for setting this that works for usual usage patterns.

We associate a this value for every object, by default being undefined . If we obtain the object through another object( test.foo ), this is set to be the base object.

New creates a new function object with this set to itself. Therefore it can be called to initialize the object. Contrary to Javascript, the constructor function has to return this .

C++ var f = function ( var x , var y ) { std :: cout < < "this: " << this ; this [ "x" ] = x ; this [ "y" ] = y ; return this ; } ; // New creates a new object this var a = new ( f ) ( 1 , 2 ) ; // this: [function 40d0] var b = new ( f ) ( 3 , 4 ) ; // this: [function 48e0] // Unbound call, var c = f ( 5 , 6 ) ; // this: undefined // Bound call var obj = { 42 } ; obj [ "f" ] = f ; var d = obj [ "f" ] ( 1 , 2 ) ; // this: [42] // Call var e = f [ "call" ] ( obj , 1 , 2 ) ; // this: [42] var f = function (var x, var y) { std::cout < < "this: " << this; this["x"] = x; this["y"] = y; return this; }; // New creates a new object this var a = new (f)(1, 2); // this: [function 40d0] var b = new (f)(3, 4); // this: [function 48e0] // Unbound call, var c = f(5, 6); // this: undefined // Bound call var obj = {42}; obj["f"] = f; var d = obj["f"](1, 2); // this: [42] // Call var e = f["call"](obj, 1, 2); // this: [42] Javascript var f = function ( x , y ) { console. log ( "this:" , this ) ; this [ "x" ] = x ; this [ "y" ] = y ; } ; // New creates a new object this var a = new f ( 1 , 2 ) ; // this: [object] var b = new f ( 3 , 4 ) ; // this: [object] // Unbound call, var c = f ( 5 , 6 ) ; // this: global object // Bound call var obj = [ 42 ] ; obj [ "f" ] = f ; var d = obj [ "f" ] ( 1 , 2 ) ; // this: [42] // Call var e = f [ "call" ] ( obj , 1 , 2 ) ; // this: [42] var f = function (x, y) { console.log("this:", this); this["x"] = x; this["y"] = y; }; // New creates a new object this var a = new f(1, 2); // this: [object] var b = new f(3, 4); // this: [object] // Unbound call, var c = f(5, 6); // this: global object // Bound call var obj = [42]; obj["f"] = f; var d = obj["f"](1, 2); // this: [42] // Call var e = f["call"](obj, 1, 2); // this: [42]

Prototypal Inheritance

In order to use prototypal inheritance, we can use Douglas Crockford Object.Create.

When reading a property, we try to read it on the current object, and if it does not exist we try again on the prototype. However, when writing a property we want to write it on the object itself. Therefore the returned object contains in fact two objects, one used for reading and one for writing.

C++ var createObject = function ( var o ) { var F = function ( ) { return this ; } ; F [ "prototype" ] = o ; return new ( F ) ( ) ; } ; var Person = { _ [ "name" ] = "Default" , _ [ "greet" ] = function ( ) { return "My name is " + this [ "name" ] ; } } ; var vjeux = createObject ( Person ) ; vjeux [ "name" ] = "Vjeux" ; var blog = createObject ( Person ) ; blog [ "name" ] = "Blog" ; var def = createObject ( Person ) ; std :: cout < < vjeux [ "greet" ] ( ) ; // Vjeux std :: cout << blog [ "greet" ] ( ) ; // Blog std :: cout << def [ "greet" ] ( ) ; // Default var createObject = function (var o) { var F = function () {return this;}; F["prototype"] = o; return new (F)(); }; var Person = { _["name"] = "Default", _["greet"] = function () { return "My name is " + this["name"]; } }; var vjeux = createObject(Person); vjeux["name"] = "Vjeux"; var blog = createObject(Person); blog["name"] = "Blog"; var def = createObject(Person); std::cout < < vjeux["greet"](); // Vjeux std::cout << blog["greet"](); // Blog std::cout << def["greet"](); // Default Javascript var createObject = function ( o ) { var F = function ( ) { } ; F. prototype = o ; return new F ( ) ; } ; var Person = { name : "Default" , greet : function ( ) { return "My name is " + this . name ; } } ; var vjeux = createObject ( Person ) ; vjeux. name = "Vjeux" ; var blog = createObject ( Person ) ; blog. name = "Blog" ; var def = createObject ( Person ) ; console. log ( vjeux. greet ( ) ) ; // Vjeux console. log ( blog. greet ( ) ) ; // Blog console. log ( def. greet ( ) ) ; // Default var createObject = function (o) { var F = function () {}; F.prototype = o; return new F(); }; var Person = { name: "Default", greet: function () { return "My name is " + this.name; } }; var vjeux = createObject(Person); vjeux.name = "Vjeux"; var blog = createObject(Person); blog.name = "Blog"; var def = createObject(Person); console.log(vjeux.greet()); // Vjeux console.log(blog.greet()); // Blog console.log(def.greet()); // Default

Iteration

We use the new iteration facility of C++0x to deal with for(var in) Javascript syntax. We just define in to be : .

As this is a prototype, it currently loops over all the keys of the object. However, it is possible to implement the isEnumerable functionnality.

C++ var array = { 10 , 42 , 30 } ; for ( var i in array ) { std :: cout < < i << " - " << array [ i ] ; } // 0 - 10 // 1 - 42 // 2 - 30 // length - 3 // prototype - undefined var object = { _ [ "a" ] = 1 , _ [ "b" ] = 2 , _ [ "c" ] = 3 } ; for ( var i in object ) { std :: cout << i << " - " << object [ i ] ; } // a - 1 // b - 2 // c - 3 // prototype - undefined var array = {10, 42, 30}; for (var i in array) { std::cout < < i << " - " << array[i]; } // 0 - 10 // 1 - 42 // 2 - 30 // length - 3 // prototype - undefined var object = { _["a"] = 1, _["b"] = 2, _["c"] = 3 }; for (var i in object) { std::cout << i << " - " << object[i]; } // a - 1 // b - 2 // c - 3 // prototype - undefined Javascript var array = [ 10 , 42 , 30 ] ; for ( var i in array ) { console. log ( i , array [ i ] ) ; } // 0 - 10 // 1 - 42 // 2 - 30 var object = { "a" : 1 , "b" : 2 , "c" : 3 } ; for ( var i in object ) { console. log ( i , object [ i ] ) ; } // a - 1 // b - 2 // c - 3 // var array = [10, 42, 30]; for (var i in array) { console.log(i, array[i]); } // 0 - 10 // 1 - 42 // 2 - 30 var object = { "a": 1, "b": 2, "c": 3 }; for (var i in object) { console.log(i, object[i]); } // a - 1 // b - 2 // c - 3 //

Dynamic Typing

There is only one class called var . All the operators + , += , ++ , < , * ... are overloaded in order to make the right behavior. Since this is only a prototype, all of them are not working properly nor following the ECMAScript standard.

C++ var repeat = function ( var str , var times ) { var ret = "" ; for ( var i = 0 ; i < times ; ++ i ) { ret += str + i ; } return ret ; } ; std :: cout << repeat ( " js++" , 3 ) ; // " js++0 js++1 js++2" var repeat = function (var str, var times) { var ret = ""; for (var i = 0; i < times; ++i) { ret += str + i; } return ret; }; std::cout << repeat(" js++", 3); // " js++0 js++1 js++2" Javascript var repeat = function ( str , times ) { var ret = "" ; for ( var i = 0 ; i < times ; ++ i ) { ret += str + i ; } return ret ; } ; console. log ( repeat ( " js++" , 3 ) ) ; // " js++0 js++1 js++2" var repeat = function (str, times) { var ret = ""; for (var i = 0; i < times; ++i) { ret += str + i; } return ret; }; console.log(repeat(" js++", 3)); // " js++0 js++1 js++2"

Scope

Scope management is done with lambdas. Since they are implemented in C++0x, it works without pain.

C++ var global = "global" ; var $ = "prototype" ; var jQuery = "jQuery" ; _ ( function ( var $ ) { var global = "local" ; std :: cout < < "Inside: $ = " << $ ; std :: cout << "Inside: global = " << global ; // Inside: $ = jQuery // Inside: global = local return undefined ; } ) ( jQuery ) ; std :: cout << "Outside: $ = " << $ ; std :: cout << "Outside: global = " << global ; // Outside: $ = prototype // Outside: global = global var global = "global"; var $ = "prototype"; var jQuery = "jQuery"; _(function (var $) { var global = "local"; std::cout < < "Inside: $ = " << $; std::cout << "Inside: global = " << global; // Inside: $ = jQuery // Inside: global = local return undefined; })(jQuery); std::cout << "Outside: $ = " << $; std::cout << "Outside: global = " << global; // Outside: $ = prototype // Outside: global = global Javascript var global = "global" ; var $ = "prototype" ; var jQuery = "jQuery" ; ( function ( $ ) { var global = "local" ; console. log ( "Inside: $ = " , $ ) ; console. log ( "Inside: global = " , global ) ; // Inside: $ = jQuery // Inside: global = local return undefined ; } ) ( jQuery ) ; console. log ( "Outside: $ = " , $ ) ; console. log ( "Outside: global = " , global ) ; // Outside: $ = prototype // Outside: global = global var global = "global"; var $ = "prototype"; var jQuery = "jQuery"; (function ($) { var global = "local"; console.log("Inside: $ = ", $); console.log("Inside: global = ", global); // Inside: $ = jQuery // Inside: global = local return undefined; })(jQuery); console.log("Outside: $ = ", $); console.log("Outside: global = ", global); // Outside: $ = prototype // Outside: global = global

Reference

As in Javascript, everything is passed by reference. The current implementation uses a simple reference count to handle garbage collection.

C++ var a = { } ; a [ "key" ] = "old" ; var b = a ; b [ "key" ] = "new" ; std :: cout < < a [ "key" ] << " " << b [ "key" ] ; // new new var a = {}; a["key"] = "old"; var b = a; b["key"] = "new"; std::cout < < a["key"] << " " << b["key"]; // new new Javascript var a = { } ; a [ "key" ] = "old" ; var b = a ; b [ "key" ] = "new" ; console. log ( a [ "key" ] , b [ "key" ] ) ; // new new var a = {}; a["key"] = "old"; var b = a; b["key"] = "new"; console.log(a["key"], b["key"]); // new new

Exception

Javascript exception mechanism is directly borrowed from C++, therefore we can use the native one.

We need to throw a Javascript object. We can either throw a new instance of a Javascript function or use _() to cast a string into an object.

C++ var go_die = function ( ) { throw "Exception!" ; } ; try { go_die ( ) ; } catch ( e ) { std :: cout < < "Error: " << e ; } // Error: Exception! var go_die = function () { throw "Exception!"; }; try { go_die(); } catch (e) { std::cout < < "Error: " << e; } // Error: Exception! Javascript var go_die = function ( ) { throw "Exception!" ; } ; try { go_die ( ) ; } catch ( e ) { console. log ( "Error:" , e ) ; } // Error: Exception! var go_die = function () { throw "Exception!"; }; try { go_die(); } catch (e) { console.log("Error:", e); } // Error: Exception!

How to use

Note: Only the strict minimum of code able to run the examples has been written. It is a prototype, do not try to use it for any serious development.

The library can be compiled under g++ 4.6, Visual Studio 2010 and the latest version of ICC. However Visual Studio and ICC do not support the initialization lists, so you cannot use the JSON syntax. But all the other examples will compile.

All the examples of this page are available in the example/ folder. The following execution will let you run the examples.

> make g++ -o example / dynamic.jspp example / dynamic.cpp -Wall -std =gnu++0x g++ -o example / exception.jspp example / exception.cpp -Wall -std =gnu++0x ... > cd example > . / json.jspp { array: [ 1 , 2 , three ] , nested: { first: 1 } , number: 42 , string: vjeux } > node json.js { number: 42 , string: 'vjeux' , array: [ 1 , 2 , 'three' ] , nested: { first: 1 } } > make g++ -o example/dynamic.jspp example/dynamic.cpp -Wall -std=gnu++0x g++ -o example/exception.jspp example/exception.cpp -Wall -std=gnu++0x ... > cd example > ./json.jspp {array: [1, 2, three], nested: {first: 1}, number: 42, string: vjeux} > node json.js { number: 42, string: 'vjeux', array: [ 1, 2, 'three' ], nested: { first: 1 } }

Pro / Cons

The awesome part is the fact that it is possible to develop nearly all the concepts of Javascript in C++.

Pros

Write C++ in a dynamic fashion!

Extremely easy to integrate all the existing C++ code base.

Fun 🙂

Cons

Not possible to optimize as much as the latest Javascript engines.

Some features are impossible to write such as eval , with , named functions ...

, , named functions ... No REPL.

A bit more verbose than Javascript.

How to Improve

Code the arguments management.

management. Develop the Javascript standard library (operators, Array, Regex ...).

Find ways to minimize the C++ overhead (remove the use of _() ).

). Find concepts that I did not introduce.

Stoyan Stefanov did a similar proof of concept but instead of targetting C++ he did it for PHP.