Slide 1

Slide 1 text

JSPP Morph C++ into Javascript

Slide 2

Slide 2 text

Quiz What programming language is it?

Slide 3

Slide 3 text

jParser.prototype.parse = function (structure) { // f, 1, 2 means f(1, 2) if (structure instanceof Function) { return structure.apply(this, Array.prototype.slice.call(arguments, 1)); } // ['string', 256] means structure['string'](256) if (structure instanceof Array) { var key = structure[0]; if (!(key in this.structure)) { throw new Error("Missing structure for `" + key + "`"); } return this.parse.apply(this, [this.structure[key]].concat(structure.slice(1))); } 3

Slide 4

Slide 4 text

static Handle ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) { Isolate* isolate = Isolate::Current(); return isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind); } static v8::Handle GetDebugEventContext(Isolate* isolate) { Handle context = isolate->debug()->debugger_entry()->GetContext(); // Isolate::context() may have been NULL when "script collected" event // occured. if (context.is_null()) return v8::Local(); Handle global_context(context->global_context()); return v8::Utils::ToLocal(global_context); } 4

Slide 5

Slide 5 text

var Utils = { _["mapInplace"] = 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 << std::endl; // [a, b, c] Utils["mapInplace"](a, function (var key, var value) { return "(" + key + ":" + value + ")"; }); std::cout << a << std::endl; // [(0:a), (1:b), (2:c)] 5

Slide 6

Slide 6 text

var Utils = { _["mapInplace"] = 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 << std::endl; // [a, b, c] Utils["mapInplace"](a, function (var key, var value) { return "(" + key + ":" + value + ")"; }); std::cout << a << std::endl; // [(0:a), (1:b), (2:c)] #include "../src/javascript_start.h" #include "../src/javascript_end.h" 5

Slide 7

Slide 7 text

Plan • JSON • Primitives • Arrays • Objects • Lambda Functions • Prototypal Inheritance 6

Slide 8

Slide 8 text

JSON var json = { "number": 42, "string": "vjeux", "array": [1, 2, "three"], "nested": { "first": true } }; 7

Slide 9

Slide 9 text

Javascript Primitives • undefined, null • true, false • Numbers • Strings var undefined, bool = true, number = 4.2, string = "JSConf"; 8

Slide 10

Slide 10 text

C++ Primitives struct Value { Value() {} // undefined Value(double n) {} // number Value(int n) {} // number Value(bool b) {} // boolean Value(const char* str) {} // string }; 9

Slide 11

Slide 11 text

C++ Primitives struct Value { Value() {} // undefined Value(double n) {} // number Value(int n) {} // number Value(bool b) {} // boolean Value(const char* str) {} // string }; Value v; Value v(4.2); Value v = "JSConf"; 9

Slide 12

Slide 12 text

C++ Primitives struct Value { Value() {} // undefined Value(double n) {} // number Value(int n) {} // number Value(bool b) {} // boolean Value(const char* str) {} // string }; Value v; Value v(4.2); Value v = "JSConf"; typedef Value var; 9

Slide 13

Slide 13 text

C++ Primitives struct Value { Value() {} // undefined Value(double n) {} // number Value(int n) {} // number Value(bool b) {} // boolean Value(const char* str) {} // string }; typedef Value var; var v; var v = "JSConf"; 9

Slide 14

Slide 14 text

C++ Primitives struct Value { Value() {} // undefined Value(double n) {} // number Value(int n) {} // number Value(bool b) {} // boolean Value(const char* str) {} // string }; typedef Value var; var undefined, boolean = true, number = 4.2, string = "JSConf"; 9

Slide 15

Slide 15 text

C++ Primitives struct Value { Value() {} // undefined Value(double n) {} // number Value(int n) {} // number Value(bool b) {} // boolean Value(const char* str) {} // string }; typedef Value var; var undefined, boolean = true, number = 4.2, string = "JSConf"; int main() { } 9

Slide 16

Slide 16 text

Trial and Error var array = A("JSConf", true, 4.2); 10

Slide 17

Slide 17 text

Trial and Error var array = A("JSConf", true, 4.2); var array = $[_, "JSConf", true, 4.2]; 10

Slide 18

Slide 18 text

Trial and Error var array = A("JSConf", true, 4.2); var array = $[_, "JSConf", true, 4.2]; var array = {"JSConf", true, 4.2}; 10

Slide 19

Slide 19 text

C++11 Initializer List struct Value { Value(std::initializer_list list); }; 11

Slide 20

Slide 20 text

Fun Fact js> {a: 1} 1 12

Slide 21

Slide 21 text

Trial and Error var json = O( "place", "JSConf", "talk", O( "length", 4.2, "pwn", true ) ); 13

Slide 22

Slide 22 text

Trial and Error var json = O( "place", "JSConf", "talk", O( "length", 4.2, "pwn", true ) ); var json = ($< "place" | "JSConf" + "talk" | ($< "length" | 4.2 + "pwn" | true >$) >$); 13

Slide 23

Slide 23 text

Trial and Error var json = O( "place", "JSConf", "talk", O( "length", 4.2, "pwn", true ) ); var json = { _["place"] = "JSConf", _["talk"] = { _["length"] = 4.2, _["pwn"] = true } }; var json = ($< "place" | "JSConf" + "talk" | ($< "length" | 4.2 + "pwn" | true >$) >$); 13

Slide 24

Slide 24 text

Precedence 1 :: 2 [] ++ -- () . -> 3 ++ -- + - ! ~ * & (type) sizeof new delete 4 .* ->* 5 * / % 6 + - 7 << >> 8 < <= > >= 9 == != 10 & 11 ^ 12 | 13 && 14 || 15 ?: 16 = += -= *= /= %= <<= >>= &= ^= |= 17 throw 18 , 14

Slide 25

Slide 25 text

Implementation { _["key"] = "value" } Underscore _; 15

Slide 26

Slide 26 text

Implementation { _["key"] = "value" } { _["key"] = "value" } struct Underscore { KeyValue& operator[](Value k); }; Underscore _; 15

Slide 27

Slide 27 text

Implementation { _["key"] = "value" } { _["key"] = "value" } { _["key"] = "value" } { _["key"] = "value" } struct Underscore { KeyValue& operator[](Value k); }; Underscore _; struct KeyValue { KeyValue(Value k); KeyValue& operator=(Value v); }; 15

Slide 28

Slide 28 text

Implementation struct Value { Value(KeyValue& kv); }; { _["key"] = "value" } { _["key"] = "value" } { _["key"] = "value" } { _["key"] = "value" } { _["key"] = "value" } struct Underscore { KeyValue& operator[](Value k); }; Underscore _; struct KeyValue { KeyValue(Value k); KeyValue& operator=(Value v); }; 15

Slide 29

Slide 29 text

Result var json = { _["number"] = 42, _["string"] = "vjeux", _["array"] = {1, 2, "three"}, _["nested"] = { _["first"] = true, _["second"] = undefined } }; var json = { number: 42, string: "vjeux", array: [1, 2, "three"], nested: { first: true, second: undefined } }; 16

Slide 30

Slide 30 text

Lambda Functions 17

Slide 31

Slide 31 text

var adder = function (x) { return function (y) { return x + y; }; }; var add5 = adder(5); // add5(1) == 6 auto adder = [] (int x) { return [=] (int y) -> int { return x + y; }; }; auto add5 = adder(5); // add5(1) == 6 C++11 Lambda 18

Slide 32

Slide 32 text

[=] (Value y) -> Value { function (y) { Macro :( 19

Slide 33

Slide 33 text

#define function (...) [=] (##__VA_ARGS__) -> Value [=] (Value y) -> Value { function (y) { Macro :( 19

Slide 34

Slide 34 text

#define function (...) [=] (##__VA_ARGS__) -> Value [=] (Value y) -> Value { function (y) { [=] (var y) -> Value { function (var y) { Macro :( 19

Slide 35

Slide 35 text

struct Value { Value(std::function f); Value(std::function f); Value(std::function f); }; Store Me 20

Slide 36

Slide 36 text

Value Value::operator()(Value a) { if (n == 0) return f0(); if (n == 1) return f1(a); if (n == 2) return f2(a, undefined); } Call Me 21

Slide 37

Slide 37 text

Value Value::operator()(Value a) { if (n == 0) return f0(); if (n == 1) return f1(a); if (n == 2) return f2(a, undefined); } Value Value::operator()() { if (n == 0) return f0(); if (n == 1) return f1(undefined); if (n == 2) return f2(undefined, undefined); } Value Value::operator()(Value a, Value b) { if (n == 0) return f0(); if (n == 1) return f1(a); if (n == 2) return f2(a, b); } Call Me 21

Slide 38

Slide 38 text

Prototypal Inheritance 22

Slide 39

Slide 39 text

Prototypal Inheritance Value& Value::operator[](Value key) { if (this->map.contains(key) { return this->map[key]; } 23

Slide 40

Slide 40 text

Prototypal Inheritance Value& Value::operator[](Value key) { if (this->map.contains(key) { return this->map[key]; } if (this->map.contains("__proto__")) { return this->map["__proto__"][key]; } 23

Slide 41

Slide 41 text

Prototypal Inheritance Value& Value::operator[](Value key) { if (this->map.contains(key) { return this->map[key]; } return undefined; } if (this->map.contains("__proto__")) { return this->map["__proto__"][key]; } 23

Slide 42

Slide 42 text

Object.Create var Object_Create = function (var parent) { return { _["__proto__"] = parent }; }; 24

Slide 43

Slide 43 text

new new (Point)(10, 20); var new = function (var ctor) { return function () { var obj = { _["__proto__"] = ctor["prototype"] }; ctor["apply"](obj, arguments); return obj; }; }; 25

Slide 44

Slide 44 text

And more ... 26

Slide 45

Slide 45 text

Closure 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 (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 27

Slide 46

Slide 46 text

This var f = function (var x, var y) { std::cout << "this: " << this; this["x"] = x; this["y"] = y; return undefined; }; // New creates a new object this var a = new (f)(1, 2); // this: [function 40d0] // 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 & Apply 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] // 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 & Apply var e = f["call"](obj, 1, 2); // this: [42]= #define function(...) [=] (var this, var arguments, ##__VA_ARGS__) -> Value

Slide 47

Slide 47 text

Operators 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) << std::endl; // " 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" 29

Slide 48

Slide 48 text

Iteration var object = { _["a"] = 1, _["b"] = 2, _["c"] = 3 }; for (var i in object) { std::cout << i << " - " << object[i]; } // a - 1 // b - 2 // c - 3 var object = { "a": 1, "b": 2, "c": 3 }; for (var i in object) { console.log(i, object[i]); } // a - 1 // b - 2 // c - 3 30 #define in :

Slide 49

Slide 49 text

Exceptions 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) { console.log("Error:", e); } // Error: Exception! 31 #define throw throw _= #define catch(e) catch(var e)

Slide 50

Slide 50 text

And less ... 32

Slide 51

Slide 51 text

• No eval • No implicit return undefined; • Different syntax for Array and Object initialization • Only boxed version of primitive types • C++ primitive types must sometimes be explicitly casted into Value • No variable hoisting • Control structures are blocks • Cannot redeclare variables in the same scope • No automatic global without var • Function arguments must be preceded by var • return; is not valid • new requires parenthesis around the constructor function Differences 33

Slide 52

Slide 52 text

• No dot notation . for object property access • The empty object notation {} is treated as undefined • Use |= instead of = to modify a closure reference • in, === and !== renamed in of, is and isnt • typeof, delete are functions instead of operators • switch case construction with integers only • Implementation dependent limit for number of arguments • No break label; form • No automatic semi-column ; insertion • No named functions • No string literal with simple quote '...' • No short regex notation /.../ • No >>>, >>>=, void operators Differences 34

Slide 53

Slide 53 text

Differences 35 No with :(

Slide 54

Slide 54 text

Differences 35 No with :( Yes goto!

Slide 55

Slide 55 text

Conclusion • Is it useful? • I don’t know. • Is it fun? • Yes, certainly! 36 • github.com/vjeux/jspp • blog.vjeux.com • twitter.com/vjeux