1 of 49

Closures

Today: Linked Stacks

2 of 49

Where are we now?

  • IMP
  • Heaps
  • Types
  • Closures
    • Scopes (Stacks)
    • Long-lived scopes (Linked Stacks)
    • Functions

3 of 49

What is a Closure?

  • A function and a scope (in which to run the function)
  • First-class: a closure is a value
  • Higher-Order: functions may take closures as arguments

var f = fun(x) {

print(x);

};

f(1);

var x = 1;

var f = fun() {

print(x);

};

f();

Output: 1

var x = 1;

var f = fun() {

x = 2;

};

print(x)

var g = fun(h) {

h();

}

print(x)

g(f);

print(x);

Output: 1

Outputs: �1�1�2

4 of 49

Challenge: Managing Scopes

A closure may refer to the value of variable from a scope that has been popped from the stack

Scope’s frame may live longer than the the single execution of the scope’s code

What do we do?

var f = 0;

{

var x = 1;

f = fun() {

print(x);

x = x + 1;

};

}

f();

f();

f();

Output:

1

2

3

5 of 49

Statements: Inference Rules

 

 

 

 

6 of 49

Expressions: Inference Rules

 

Integer

Constant

Variable

Reference

Unary

Minus

 

 

 

 

 

7 of 49

Statements: Inference Rules

 

 

{

var x = 1;

var x = 2;

}

8 of 49

Statements: Inference Rules

 

 

9 of 49

Update

  •  

 

 

10 of 49

Challenge: Managing Scopes

A closure may refer to the value of variable from a scope that has been popped from the stack

Scope’s frame may live longer than the the single execution of the scope’s code

What do we do?

var f = 0;

{

var x = 1;

f = fun() {

print(x);

x = x + 1;

};

}

f();

f();

f();

Output:

1

2

3

11 of 49

Closures versus “Functions”

void f() {

int x = 1;

printf(“%d\n”, x);

x = x + 1;

}

void f() {

static int x = 1;

printf(“%d\n”, x);

x = x + 1;

}

int x = 1;

void f() {

printf(“%d\n”, x);

x = x + 1;

}

void main(...) {

f(); f(); f();

}

var f = 0;

{

var x = 1;

f = fun() {

print(x);

x = x + 1;

};

}

f();

f();

f();

Output:

1

1

3

12 of 49

Closures versus “Functions” (C++ Attempt)

void f() {

int x = 1;

printf(“%d\n”, x);

x = x + 1;

}

void f() {

static int x = 1;

printf(“%d\n”, x);

x = x + 1;

}

int f_x = 1;

void f() {

printf(“%d\n”, f_x);

f_x = f_x + 1;

}

void main(...) {

f(); f(); f();

}

Output:

1

1

1

Output:

1

2

3

Output:

1

2

3

13 of 49

Challenge: Managing Scopes

var f = 0;

{

var x = 1;

f = fun() {

print(x);

x = x + 1;

};

}

f();

f();

f();

Output:

1

2

3

var g = fun() {

var x = 1;

var f = fun() {

print(x);

x = x + 1;

};

return f;

};

g()();

g()();

g()();

Output:

1

1

1

14 of 49

Challenge: Managing Scopes

A closure may refer to the value of variable from a scope that has been popped from the stack

Scope’s frame may live longer than the the single execution of the scope’s code

What do we do?

var f = 0;

{

var x = 1;

f = fun() {

print(x);

x = x + 1;

};

}

f();

f();

f();

Output:

1

2

3

Allocate frames in the heap!

15 of 49

Closures versus “Functions”

struct FClosure {

int x;

FClosure() : x() { }

int f() {

printf(“%d\n”, this.x);

this.x = this.x + 1;

}

};

FClosure* g() { return new FClosure();}

int main(...)

{

g()->f(); g()->f(); g()->f();

}

var g = fun() {

var x = 1;

var f = fun() {

print(x);

x = x + 1;

};

return f;

};

g()();

g()();

g()();

16 of 49

These are Automation (plus more)

f = lambda x, y : x + y

var f = function(x, y) {

return x + y;

}

var f = (x, y) => {

return x + y;

}

auto f = [](int x, int y) {

return x + y;

};

BinaryOperator<int> f = (int x, int y) -> {

return x + y;

};

Python

C++

Java

Javascript

17 of 49

Extending IMP with Closures

  • Syntax: create and call closures

  • Representation: closures are values and frames are long-lived

  • Semantics: creating and calling closures

18 of 49

Extending IMP with Closures

  • Syntax: create and call closures

  • Representation: closures are values and frames are long-lived

  • Semantics: creating and calling closures

19 of 49

Add Closures: Grammar

 

 

 

 

(call closure)

 

20 of 49

Extending IMP with Closures

  • Syntax: create and call closures

  • Representation: closures are values and frames are long-lived

  • Semantics: creating and calling closures

21 of 49

Linked Stacks

1: var x = 1;

2: var y = 2;

3: {

4: var x = 3;

5: y = 4;

6: }

Line

Frame Pointer

Heap (h)

1

2

3

4

5

6

“ ”

22 of 49

Linked Stacks

1: var x = 1;

2: var y = 2;

3: {

4: var x = 3;

5: y = 4;

6: }

Line

Frame Pointer

Heap (h)

1

100

{100 : {x : 200}, � 200 : 1}

2

100

3

108

4

108

5

108

6

100

23 of 49

Linked Stacks

1: var x = 1;

2: var y = 2;

3: {

4: var x = 3;

5: y = 4;

6: }

Line

Frame Pointer

Heap (h)

1

100

{100 : {x : 200}, � 200 : 1}

2

100

{100 : {x : 200, y : 208}, � 200 : 1, 208 : 2}

3

108

4

108

5

108

6

100

24 of 49

Linked Stacks

1: var x = 1;

2: var y = 2;

3: {

4: var x = 3;

5: y = 4;

6: }

Line

Frame Pointer

Heap (h)

1

100

{100 : {x : 200}, � 200 : 1}

2

100

{100 : {x : 200, y : 208}, � 200 : 1, 208 : 2}

3

108

{100 : {x : 200, y : 208}, 108 : {p : 100}, � 200 : 1, 208 : 2}

4

108

5

108

6

100

25 of 49

Linked Stacks

1: var x = 1;

2: var y = 2;

3: {

4: var x = 3;

5: y = 4;

6: }

Line

Frame Pointer

Heap (h)

1

100

{100 : {x : 200}, � 200 : 1}

2

100

{100 : {x : 200, y : 208}, � 200 : 1, 208 : 2}

3

108

{100 : {x : 200, y : 208}, 108 : {p : 100}, � 200 : 1, 208 : 2}

4

108

{100 : {x : 200, y : 208}, 108 : {p : 100, x : 216}, 200 : 1, 208 : 2, 216 : 3}

5

108

6

100

26 of 49

Linked Stacks

1: var x = 1;

2: var y = 2;

3: {

4: var x = 3;

5: y = 4;

6: }

Line

Frame Pointer

Heap (h)

1

100

{100 : {x : 200}, � 200 : 1}

2

100

{100 : {x : 200, y : 208}, � 200 : 1, 208 : 2}

3

108

{100 : {x : 200, y : 208}, 108 : {p : 100}, � 200 : 1, 208 : 2}

4

108

{100 : {x : 200, y : 208}, 108 : {p : 100, x : 216}, 200 : 1, 208 : 2, 216 : 3}

5

108

{100 : {x : 200, y : 224}, 108 : {p : 100, x : 216}, 200 : 1, 208 : 2, 216 : 3, 224 : 4}

6

100

27 of 49

Linked Stacks

1: var x = 1;

2: var y = 2;

3: {

4: var x = 3;

5: y = 4;

6: }

Line

Frame Pointer

Heap (h)

1

100

{100 : {x : 200}, � 200 : 1}

2

100

{100 : {x : 200, y : 208}, � 200 : 1, 208 : 2}

3

108

{100 : {x : 200, y : 208}, 108 : {p : 100}, � 200 : 1, 208 : 2}

4

108

{100 : {x : 200, y : 208}, 108 : {p : 100, x : 216}, 200 : 1, 208 : 2, 216 : 3}

5

108

{100 : {x : 200, y : 224}, 108 : {p : 100, x : 216}, 200 : 1, 208 : 2, 216 : 3, 224 : 4}

6

100

“ ”

28 of 49

Frames, Heaps, Linked Stacks, and Closures

  •  

29 of 49

Evaluation Relations (with heaps and stacks)

 

 

 

  • Define the semantics of each term in our language (E, B, and S) with an evaluation relation:

  • Meaning: given a stack, and heap, the term evaluates to a result

30 of 49

Evaluation Relations (with linked stacks)

  • Define the semantics of each term in our language (E, B, and S) with an evaluation relation:

  • Meaning: given a frame pointer, and heap, the term evaluates to a result

 

 

 

31 of 49

Expressions: Inference Rules

 

 

Integer

Constant

Variable

Reference

 

 

 

Unary

Minus

32 of 49

Lookup

  •  

 

 

33 of 49

Expressions: Inference Rules

 

 

Integer

Constant

Variable

Reference

 

 

Unary

Minus

 

 

34 of 49

Inference Rules: Declaration

 

 

 

 

 

 

 

 

In-place update

35 of 49

Inference Rules: Assignment

 

 

36 of 49

Update

  •  

 

 

37 of 49

Inference Rules: Block Scope

 

 

 

 

38 of 49

Extending IMP with Closures

  • Syntax: create and call closures

  • Representation: closures are values and frames a long-lived

  • Semantics: creating and calling closures

39 of 49

Inference Rules: Closure Creation (Declaration)

 

 

 

 

 

 

 

 

40 of 49

Inference Rules: Closure Creation

 

 

  • Execution: capture frame pointer

41 of 49

Managing Scope (Revisited)

1: var f = 0;

2: {

3: var x = 1;

4: f = fun(y) {

5: print(x);

6: x = x + 1;

7: };

8: }

9: f(1);

10: f(2);

Line

FP (a)

Heap (h)

1

200

3

208

7

208

8

200

9

200

10

200

42 of 49

Managing Scope (Revisited)

1: var f = 0;

2: {

3: var x = 1;

4: f = fun(y) {

5: print(x);

6: x = x + 1;

7: };

8: }

9: f(1);

10: f(2);

Line

FP (a)

Heap (h)

1

200

{ 100 : 0, 200: {f : 100}}

3

208

7

208

8

200

9

200

10

200

43 of 49

Managing Scope (Revisited)

1: var f = 0;

2: {

3: var x = 1;

4: f = fun(y) {

5: print(x);

6: x = x + 1;

7: };

8: }

9: f(1);

10: f(2);

Line

FP (a)

Heap (h)

1

200

{ 100 : 0, 200: {f : 100}}

3

208

{ 100 : 0, 108 : 1, 200 : {f : 100}, 208 : {p : 200, x : 108} }

7

208

8

200

9

200

10

200

44 of 49

Managing Scope (Revisited)

1: var f = 0;

2: {

3: var x = 1;

4: f = fun(y) {

5: print(x);

6: x = x + 1;

7: };

8: }

9: f(1);

10: f(2);

Line

FP (a)

Heap (h)

1

200

{ 100 : 0, 200: {f : 100}}

3

208

{ 100 : 0, 108 : 1, 200 : {f : 100}, 208 : {p : 200, x : 108} }

7

208

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

8

200

9

200

10

200

45 of 49

Managing Scope (Revisited)

1: var f = 0;

2: {

3: var x = 1;

4: f = fun(y) {

5: print(x);

6: x = x + 1;

7: };

8: }

9: f(1);

10: f(2);

Line

FP (a)

Heap (h)

1

200

{ 100 : 0, 200: {f : 100}}

3

208

{ 100 : 0, 108 : 1, 200 : {f : 100}, 208 : {p : 200, x : 108} }

7

208

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

8

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

9

200

10

200

46 of 49

Managing Scope (Revisited)

1: var f = 0;

2: {

3: var x = 1;

4: f = fun(y) {

5: print(x);

6: x = x + 1;

7: };

8: }

9: f(1);

10: f(2);

Line

FP (a)

Heap (h)

1

200

{ 100 : 0, 200: {f : 100}}

3

208

{ 100 : 0, 108 : 1, 200 : {f : 100}, 208 : {p : 200, x : 108} }

7

208

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

8

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

9

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ), 124:1, 132:2

200 : {f : 116}, 208 : {p : 200, x : 132} , 212 : {p : 208, y: 124} }

10

200

47 of 49

Managing Scope (Revisited)

1: var f = 0;

2: {

3: var x = 1;

4: f = fun(y) {

5: print(x);

6: x = x + 1;

7: };

8: }

9: f(1);

10: f(2);

Line

FP (a)

Heap (h)

1

200

{ 100 : 0, 200: {f : 100}}

3

208

{ 100 : 0, 108 : 1, 200 : {f : 100}, 208 : {p : 200, x : 108} }

7

208

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

8

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

9

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ), 124:1, 132:2

200 : {f : 116}, 208 : {p : 200, x : 132} , 212 : {p : 208, y: 124} }

10

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ), 124: 1, 132:2,

140: 2, 148: 3

200 : {f : 116}, 208 : {p : 208, x : 132} }, 212 : {p : 208, y : 124} ,

216 : {p : 208, y : 140} }

48 of 49

Inference Rules: Closure Execution

  •  

 

 

 

 

 

 

x Evaluates to a closure

E evaluates to a value

Create a new frame

Evaluate body of closure

 

 

 

49 of 49

Managing Scope (Revisited)

Line

FP (a)

Heap (h)

1

200

{ 100 : 0, 200: {f : 100}}

3

208

{ 100 : 0, 108 : 1, 200 : {f : 100}, 208 : {p : 200, x : 108} }

7

208

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

8

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ),

200 : {f : 116}, 208 : {p : 200, x : 108} }

9

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ), 124: 2,

200 : {f : 116}, 208 : {p : 200, x : 124} , 212 : {p : 208} }

10

200

{ 100 : 0, 108 : 1, 116 : (208, y, {print(x); x = x + 1} ), 124: 2, 132:3

200 : {f : 116}, 208 : {p : 208, x : 132} }, 212 : {p : 208} ,

216 : {208} }

1: var f = 0;

2: {

3: var x = 1;

4: f = fun() {

5: print(x);

6: x = x + y;

7: };

8: var y = 2;

9: }

10: f(1);

11: f(2);