+ - 0:00:00
Notes for current slide
Notes for next slide

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

CS450

Structure of Higher Level Languages

Lecture 38: SimpleJS; translating LambdaJS to SimpleJS

Tiago Cogumbreiro

1 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

My goal with CS450 is to teach you …

1. Fundamental concepts behind most programming languages

  • functional programming, delayed evaluation, control flow and exceptions, object oriented systems, monads, macros, pattern matching, variable scoping, immutable data structures

2. A framework to describe language concepts

  • λ\lambda-calculus and formal systems to specify programming languages
  • functional programming and monads to implement specifications

3. A methodology to understand complex systems

  • (formally) specify and implement each programming language feature separately
  • understand a complex system as a combination of smaller simpler systems
  • implement and test features independently
2 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Today we will…

  • Revise JavaScript's object system
  • Introduce SimpleJS: S-Expression-based syntax and simpler JavaScript rules
  • Introduce LambdaJS: λ\lambda-calculus + references + immutable objects
  • Introduce translation from SimpleJS into LambdaJS

Why are we learning all SimpleJS and LambdaJS?

  • You already know λ\lambda-calculus with references (heap)
  • You already know how objects work (ie, a map with a lookup that work like frames and environments)
  • I want to teach you the fundamentals of JavaScript by building it on top of concepts that you already know!
  • I can introduce another kind of specifying the semantics of a system, by translating it into another system (denotational semantics)
3 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Object prototypes

A.__proto__ = B links A object to B, if a field f is not available in A, then it is looked up in B (which works recursively until finding undefined).

 

a = {"x": 10, "y": 20}
b = {"x": 30, "z": 90, "__proto__": a}
b {x: 30, z: 90, *y: 20}

Functions are constructors

If we call a function A with new, then A is called as the constructor of a new object.

 

function C(x, y) { this.x = x; this.y = y }
c = new C(10, 20)
c {x: 10, y: 20}

Constructor's prototype

If A is a function, then A.prototype becomes the __proto__ of every object created using A with new.

 

C.prototype = {"foo": true, "bar": 100}
d = new C(10, 20)
d {x: 10, y: 20, *foo: true, *bar: 100}
4 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Quiz

What is the name of the paper we are studying?

5 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

SimpleJS

6 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Introducing SimpleJS

  • SimpleJS is just a simplification of JavaScript with fewer corner case, which is easier to learn.
  • SimpleJS was created by your instructor for CS450 (yet close to what you have in The Essence of JavaScript)
  • SimpleJS has a formal syntax (below) and also an S-expression syntax (hw8-util.rkt)
  • Today we will formally describe SimpleJS in terms of how we can represent it in LambdaJS (defined in The Essence of JavaScript).
e::=xlet x=e in ex.yx.y:=ex.y(e)function(x){e}new e(e)class extends e {constructor(x){e} m}m::=x(x){e}e ::= x \mid \texttt{let}\ x = e\ \texttt{in}\ e \mid x.y \mid x.y := e \mid x.y(e\cdots) \\ \mid \texttt{function}( x \cdots) \{ e \} \mid \texttt{new}\ e(e \cdots) \\ \mid \texttt{class extends} \ e\ \{ \texttt{constructor}(x\cdots) \{ e \} \ m \cdots \} \\[1em] m ::= x(x\cdots) \{ e \}
7 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Writing Shape in SimpleJS

JavaScript

function Shape(x, y) {
this.x = x;
this.y = y;
}
let p = new Shape(10, 20);
Shape.prototype.translate =
function(x, y) {
this.x = this.x + x;
this.y = this.y + y;
};
p.translate(1,2);
return p;

SimpleJS

(let Shape
(function (x y)
(begin (set! this.x x)
(set! this.y y)))
(let p (new Shape 10 20)
(let Shape-proto Shape.prototype
(begin
(set! Shape-proto.translate
(function (x y)
(begin
(set! this.x (! + this.x x))
(set! this.y (! + this.y y)))))
(p.translate 1 2)
p))))
8 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Writing Rectangle in SimpleJS

JavaScript

function Rectangle(width, height) {
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
}
Rectangle.prototype =
Shape.prototype;
let r1 = new Rectangle(10, 20);
return r1;

SimpleJS

(let Rectangle
(function (width height)
(begin
(set! this.x 0)
(set! this.y 0)
(set! this.width width)
(set! this.height height)))
(set! Rectangle.prototype Shape.prototype)
(let r1 (new Rectangle 10 20)
r1))

9 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Writing Rectangle in SimpleJS

JavaScript

function Rectangle(width, height) {
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
}
Rectangle.prototype =
Shape.prototype;
let r1 = new Rectangle(10, 20);
return r1;

SimpleJS

(let Rectangle
(function (width height)
(begin
(set! this.x 0)
(set! this.y 0)
(set! this.width width)
(set! this.height height)))
(set! Rectangle.prototype Shape.prototype)
(let r1 (new Rectangle 10 20)
r1))

What are the possible problems of this form of inheritance?

9 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Writing Rectangle in SimpleJS

JavaScript

function Rectangle(width, height) {
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
}
Rectangle.prototype =
Shape.prototype;
let r1 = new Rectangle(10, 20);
return r1;

SimpleJS

(let Rectangle
(function (width height)
(begin
(set! this.x 0)
(set! this.y 0)
(set! this.width width)
(set! this.height height)))
(set! Rectangle.prototype Shape.prototype)
(let r1 (new Rectangle 10 20)
r1))

What are the possible problems of this form of inheritance?

How can we add a new method to Rectangle?

9 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Writing Rectangle in SimpleJS

With the highlighted pattern we can safely mutate Rectangle.prototype. This is the same as Rectangle.prototype = {'__proto__': Shape.prototype }, but we have no syntax for such a pattern in SimpleJS.

JavaScript

function Rectangle(width, height) {
this.x = 0;
this.y = 0;
this.width = width;
this.height = height;
}
let p = function () {}
p.prototype = Shape.prototype;
Rectangle.prototype = new p();
let r1 = new Rectangle(10, 20);
return r1;

SimpleJS

(let Rectangle
(function (width height)
(begin (set! this.x 0) (set! this.y 0)
(set! this.width width)
(set! this.height height)))
(let p (function () 0)
(begin
(set! p.prototype = Shape.prototype)
(set! Rectangle.prototype (new p))
(let r1 (new Rectangle 10 20)
r1))))

10 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

LambdaJS

11 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

LambdaJS

Think Racket without define, without macros, with objects, and heap operations.

Expressions

e::=vxλx.ee(e){s ⁣:e}e[e]e[e]ealloc ee:=ee ::= {\color{blue} v \mid x \mid \lambda x.e \mid e(e)} \mid {\color{purple} \{s \colon e\}\mid e[e] \mid e[e] \leftarrow e } \mid {\color{green} \mathtt{alloc}\ e \mid e := e}
12 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Concrete LambdaJS S-expression syntax

Formal syntax S-expression
λx.e\lambda x.e (lambda (x) e)
e1(e2)e_1(e_2) (e1 e2)
{"foo":1+2,"bar":x}\{\texttt{"foo"}: 1 + 2, \texttt{"bar"}: x\} (object ["foo" (+ 1 2)] ["bar" x])
o["foo"]o[\texttt{"foo"}] (get-field o "foo")
alloc {}\texttt{alloc}\ \{\} (alloc (object))
x:={}x := \{\} (set! x (object))
x:=1;xx := 1; x (begin (set! x 1) x)
let x = 10 in x+4\mathsf{let}\ x\ =\ 10\ \mathsf{in}\ x + 4 (let ([x 10]) (+ x 4))

In Racket you can actually allocate a reference with (box e), which is equivalent to LambdaJS(alloc e), and update the contents of that reference with (set-box! b e), which is equivalent to LambdaJS (set! e).

13 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating SimpleJS into LambdaJS

Overview

14 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating SimpleJS into LambdaJS

  1. A SimpleJS object is represented as a reference to an immutable LambdaJS object
  2. A SimpleJS function is represented as an object with two fields: (a) a lambda-function that represents the code, a prototype field which points to an empty SimpleJS object
  3. Create an object with new expects a SimpleJS function as argument and must create a new object, initialize its prototype, and call the constructor function (see point 2)
  4. Method invocation corresponds to accessing a SimpleJS function and passing the implicit this object to it (see 2)

Objectives of the translation

  • Explicit this
  • Functions are not objects: convert function into an object+lambda
  • Explicit memory manipulation
  • No method calls: use function calls
15 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating a function

JavaScript

function Shape(x, y) {
this.x = x;
this.y = y;
};

Step 1: only objects and lambdas

Shape = {
'$code': (obj, x, y) => {
obj.x = x;
obj.y = y;
},
'prototype' = {}
};
16 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating a function

JavaScript

function Shape(x, y) {
this.x = x;
this.y = y;
};

Step 1: only objects and lambdas

Shape = {
'$code': (obj, x, y) => {
obj.x = x;
obj.y = y;
},
'prototype' = {}
};

Step 2: explicit references

Shape = alloc {'$code': (this, x, y) => {
this = (deref this)["x"] <- x; // In LambdaJS we have to replace the whole object
this = (deref this)["y"] <- y;},
'prototype': alloc {}};
16 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating new

JavaScript

p1 = new Shape(0, 1);

Step 1: only objects and lambdas; no implicit this

p1 = {"__proto__": Shape.prototype};
Shape["$code"](file:///home/tiago/Work/cs450-slides/p1, 0, 1);
17 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating new

JavaScript

p1 = new Shape(0, 1);

Step 1: only objects and lambdas; no implicit this

p1 = {"__proto__": Shape.prototype};
Shape["$code"](file:///home/tiago/Work/cs450-slides/p1, 0, 1);

Step 2: explicit references

p1 = alloc {"__proto__": (deref Shape)["prototype"]}};
(deref Shape)["$code"](file:///home/tiago/Work/cs450-slides/p1, 0, 1);
17 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating method invocation

JavaScript

p1.translate(10, 20);

Step 1: only objects and lambdas; no implicit this

m = p1["translate"]; // get object method
m["$code"](file:///home/tiago/Work/cs450-slides/p1, 10, 20); // get code for method
18 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating method invocation

JavaScript

p1.translate(10, 20);

Step 1: only objects and lambdas; no implicit this

m = p1["translate"]; // get object method
m["$code"](file:///home/tiago/Work/cs450-slides/p1, 10, 20); // get code for method

Step 2: explicit references

Formally

m = (deref p1)["translate"];
(deref m)["$code"](file:///home/tiago/Work/cs450-slides/p1, 10, 20);

SimpleJS

(let ([m (get-field (deref p1) "translate")])
((get-field (deref m) "$code") p1 10 20))
18 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translating SimpleJS into LambdaJS

Before

Shape.prototype.translate = function(x, y) {
this.x += x; this.y += y;
};
p1 = new Shape(0, 1);
p1.translate(10, 20);

After

// 1. Function declaration
Shape = alloc {
"$code": (this, x, y) => { ... },
"prototype" = alloc {}};
p = (deref Shape)["prototype"];
(deref p)["translate"] = alloc {
"$code": (this, x, y) => { ... }
"prototype": alloc {}};
// 2. new
p1 = alloc {"__proto__":
(deref Shape)["prototype"]};
(deref Shape)["$code"](file:///home/tiago/Work/cs450-slides/p1, 0, 1);
// 3. method call
f = (deref p1)["translate"];
(deref f)["$code"](file:///home/tiago/Work/cs450-slides/p1, 10, 20);
19 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translation function

20 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Translation function

  • Field lookup
  • Field update
  • Function declaration
  • The new keyword
  • Method call
  • Class declaration
21 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Field lookup

22 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Field lookup

J[ ⁣[x.y] ⁣]=(deref x)["y"]\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} % % \trans{x.y} = (\Ederef x)[\str{y}]

SimpleJS

this.x

λ\lambda-JS

(get-field (deref this) "x")
23 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Field update

24 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Field update

In JavaScript, assigning an expression ee into a field, returns the evaluation of ee. However, in LambdaJS assignment returns the reference being mutated.

J[ ⁣[x.y:=e] ⁣]= let data=J[ ⁣[e] ⁣] inx:=(deref obj)["y"]data;data\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} % % \trans{x.y := e} =\ \\ \lete {data} {\trans{e}} \\ x := (\Ederef{\mathsf{obj}})["y"] \leftarrow \mathsf{data} ; \\ \mathsf{data}

SimpleJS

(set! this.x x)

λ\lambda-JS

(let [(data x)]
(begin
(set! this
(update-field (deref this) "x" data))
data)))
25 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Free variables and bound variables

J[ ⁣[x.y:=e] ⁣]=let data=J[ ⁣[e] ⁣] in x:=(deref x)["y"]data;data\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} % % \trans{x.y := e} = \lete {data} {\trans{e}}\ \mathsf{x} := (\Ederef{\mathsf{x}})["y"] \leftarrow \mathsf{data} ; \mathsf{data}

SimpleJS

(set! data.x 10)

λ\lambda-JS

(let [(data 10)]
(begin
(set! data
(update-field (deref data) "x" data))
data)))

What happened here?

26 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Free variables and bound variables

J[ ⁣[x.y:=e] ⁣]=let data=J[ ⁣[e] ⁣] in x:=(deref x)["y"]data;data\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} % % \trans{x.y := e} = \lete {data} {\trans{e}}\ \mathsf{x} := (\Ederef{\mathsf{x}})["y"] \leftarrow \mathsf{data} ; \mathsf{data}

SimpleJS

(set! data.x 10)

λ\lambda-JS

(let [(data 10)]
(begin
(set! data
(update-field (deref data) "x" data))
data)))

What happened here?

  1. Variable data is used in the generated code
  2. We must ensure that data is not captured (free) in the generated code!
26 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Quiz

What problem occurs when generating code?

(One sentence is enough.)

27 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Function declaration

28 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Function declaration

Field prototype can be accessed by the user, so we declare it as a reference. Field $code does not actually exist in JavaScript, so we prefix it with a dollar sign ($) to visually distinguish artifacts of the translation.

J[ ⁣[function(x) {e}] ⁣]=xalloc {"$code":λ(this,x).J[ ⁣[e] ⁣],"prototype":alloc {}}\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} % % \trans{\texttt{function}(x \cdots)\ \{ e \} } = \phantom{x} \\ \Eref{\{ \str{\$code}: \lambda (\mathsf{this}, \mathsf{x}\cdots).\trans{e}, \str{prototype}: \mathbf{\mathsf{alloc}}\ \{ \} \}}

SimpleJS

(function (x y)
(begin
(set! this.x x)
(set! this.y y)))

λ\lambda-JS

(let ([js-set!
(lambda (o f d)
(begin (set! o (update-field (deref o) f d)) d))])
(alloc (object
["$code"
(lambda (this x y)
(begin (js-set! this "x" x)
(js-set! this "y" y)))]
["prototype" (alloc (object))])))
29 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

The new keyword

30 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

The new keyword

J[ ⁣[new ef(e)] ⁣]=xlet ctor=deref J[ ⁣[ef] ⁣] inlet obj=alloc {"$proto":ctor["prototype"]} inctor["$code"](file:///home/tiago/Work/cs450slides/obj,J[ ⁣[e] ⁣]);obj\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} % % \trans{\texttt{new}\ e_f(e \cdots) } = \phantom{x}\\ \lete {ctor} {\Ederef {\trans{e_f}}} \\ \lete {obj} {\Eref{\{ \proto: \mathsf{ctor}[\str{prototype}] \} }} \\ \mathsf{ctor}[\str{\$code}](file:///home/tiago/Work/cs450-slides/\mathsf{obj}, \trans{e}\cdots);\\ \mathsf{obj}

SimpleJS

(new Shape 0 1)

λ\lambda-JS

(let [(ctor (deref Shape))
(o (alloc (object "$proto" (get-field ctor "prototype"))))]
(begin
((get-field ctor "$code") o 0 1)
o))
31 / 36

The new keyword (still incorrect)

J[ ⁣[new ef(e)] ⁣]=xlet ctor=deref J[ ⁣[ef] ⁣] inlet y=J[ ⁣[e] ⁣] inlet obj=alloc {"$proto":ctor["prototype"]} inctor["$code"](file:///home/tiago/Work/cs450slides/obj,y);obj\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} % % \trans{\texttt{new}\ e_f(e \cdots) } = \phantom{x}\\ \lete {ctor} {\Ederef {\trans{e_f}}} \\ \lete {y} {\trans{e}} \cdots \\ \lete {obj} {\Eref{\{ \proto: \mathsf{ctor}[\str{prototype}] \} }} \\ \mathsf{ctor}[\str{\$code}](file:///home/tiago/Work/cs450-slides/\mathsf{obj}, \mathsf{y} \cdots);\\ \mathsf{obj}

SimpleJS

(new Shape 0 1)

λ\lambda-JS

(let [(ctor (deref Proto))
(o (alloc (object "$proto" (get-field ctor "prototype"))))
(y1 0) (y2 1)]
(begin
((get-field ctor "$code") o y1 y2)
o))

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Method invocation

32 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Method invocation

J[ ⁣[x.y(e)]] ⁣]=((deref ((deref x)["y"]))["$code"])(x,J[ ⁣[e] ⁣])\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } % % \trans{x.y(e\cdots)]} = {\color{red}\Big(} {\color{purple}\big(} \Ederef{ {\color{green}\big(} {\color{blue} (\Ederef{x})}[\str{y}] {\color{green}\big)} } {\color{purple}\big)} [\str{\$code}]{\color{red}\Big)}(x, \trans{e\cdots})

SimpleJS

(p1.translate 10 20)

λ\lambda-JS

((get-field
(deref (get-field (deref p1) "translate"))
"$code")
p1 10 20)
;; In Racket pseudo code
(define p1:obj (deref p1)) ; 1. get obj from ref
(define translate:m (get-field p1-obj "translate")) ; 2. get field
(define translate:o (deref translate-m)) ; 3. get object from ref
(define translate:f (get-field translate-obj "$code") ; 4. get fun
(translate-code p1 10 20) ; 5. call fun pass this (p1)
33 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Function call

We will not be implementing function calls in Homework Assignment 8.

J[ ⁣[ef(e)] ⁣]=xlet obj=J[ ⁣[eo] ⁣] in(deref obj)["$code"](file:///home/tiago/Work/cs450slides/window,J[ ⁣[e] ⁣])\newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{J}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\Eref}[1]{\mathbf{\mathsf{alloc}}\ {#1}} \newcommand{\Ederef}[1]{\mathbf{\mathsf{deref}}\ {#1}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } % % \trans{e_f(e\cdots)} = \phantom{x} \\ \lete {obj} {\trans{e_o}} \\ (\Ederef{\mathsf{obj}})[\str{\$code}](file:///home/tiago/Work/cs450-slides/{\color{red}\mathsf{window}}, \trans{e\cdots})

Example 1

class Foo {
constructor() { this.x = 0; }
bar() { this.x++; }
}
var foo = new Foo();
foo["bar"](file:///home/tiago/Work/cs450-slides/); // foo.bar();
// Caveat: foo.bar() != (foo.bar)()

Example 2

class Foo {
constructor() { this.x = 0; }
bar() { this.x++; }
}
var foo = new Foo();
var bar = foo["bar"];
bar(); // TypeError: this is undefined
34 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Class declaration

35 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

Class declaration

To allow dynamically dispatching to XX's methods, the first four lines instantiate XX without calling its constructor. This way, we can safely mutate the cls\mathsf{cls}'s prototype without affecting XX and any changes to XX are visible to cls\mathsf{cls} via lookup.

C[ ⁣[class extends X {body}] ⁣]=xlet parent=C[ ⁣[X] ⁣] inlet parent=function (){} inparent.prototype:=parent.prototypelet proto=new parent inlet cls=function (x){ec} incls.prototype:=proto;proto.m:=function(y){em};clswhere body=constructor(x){ec} m(y){em}\small \newcommand{\str}[1]{\texttt{\color{blue}"{#1}"}} \newcommand{\proto}{\str{\$proto}} \newcommand{\trans}[1]{{\color{brown}\mathrm{C}\textbf{[\![}}{#1}{\color{brown}\textbf{]\!]}}} \newcommand{\lete}[2]{ \mathbf{\mathsf{let}}\ \mathsf{{#1}} = {#2} \ \mathbf{\mathsf{in}} } % % \trans{\texttt{class}\ \texttt{extends}\ X\ \{ body \} } = \phantom{x} \\ {\color{purple}\lete {parent} {\trans{X}}} \\ {\color{purple} \lete {parent'} {\mathtt{function}\ ()\{\}} }\\ {\color{purple} \mathsf{parent'.prototype} := \mathsf{parent.prototype} }\\ {\color{purple} \lete {proto} {\mathtt{new}\ \mathsf{parent'}} }\\ \lete {cls} {\mathtt{function}\ (x \cdots) \{ e_c \}}\\ \mathsf{cls.prototype} := {\color{purple} \mathsf{proto}}; \\ {\color{purple} \mathsf{proto}}.\mathsf{m} := \texttt{function}(y\cdots) \{ e_m \}; \cdots\\ \mathsf{cls} \\[.3em] \text{where } body = \mathtt{constructor}(x \cdots) \{ e_c \}\ m(y \cdots) \{ e_m \} \cdots
36 / 36

CS450  ☽  SimpleJS; translating LambdaJS to SimpleJS  ☽  Lecture 38  ☽  Tiago Cogumbreiro

My goal with CS450 is to teach you …

1. Fundamental concepts behind most programming languages

  • functional programming, delayed evaluation, control flow and exceptions, object oriented systems, monads, macros, pattern matching, variable scoping, immutable data structures

2. A framework to describe language concepts

  • λ\lambda-calculus and formal systems to specify programming languages
  • functional programming and monads to implement specifications

3. A methodology to understand complex systems

  • (formally) specify and implement each programming language feature separately
  • understand a complex system as a combination of smaller simpler systems
  • implement and test features independently
2 / 36
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow