Scope Deian Stefan (adopted from my & Edward Yangs CSE242 - - PowerPoint PPT Presentation

scope
SMART_READER_LITE
LIVE PREVIEW

Scope Deian Stefan (adopted from my & Edward Yangs CSE242 - - PowerPoint PPT Presentation

Scope Deian Stefan (adopted from my & Edward Yangs CSE242 slides) Substitution model Way of giving semantics to the -calculus E.g., ( x.f x x) ( y.z) f ( y.z) ( y.z) Translate this knowledge to JavaScript


slide-1
SLIDE 1

Scope

Deian Stefan (adopted from my & Edward Yang’s CSE242 slides)

slide-2
SLIDE 2

Substitution model

  • Way of giving semantics to the λ-calculus

➤ E.g., (λx.f x x) (λy.z) →β f (λy.z) (λy.z)

  • Translate this knowledge to JavaScript functions

➤ (x => f(x)(x)) (y => z) →β f(y => z)(y => z)

slide-3
SLIDE 3
  • Why would you, in practice, not really want to do

function application in this way for a language like JavaScript?

➤ It’s super slow! Why? ➤ It’s actually nonsensical sometimes! When?

Substitution model

slide-4
SLIDE 4

Substitution gone wrong

  • Consider variable mutation in JavaScript:


let y = 1;
 let z = 0; ...
 z++; →β. 0++;
 console.log(z); ...

  • There is nothing wrong with substitution per say

➤ It’s symbolic evaluation/computation ➤ Problem is JavaScript has mutation and not

amendable to symbolic evaluation

slide-5
SLIDE 5

What can we do?

tomfishburne.com

λ-calculus machine model environment model

slide-6
SLIDE 6

The environment model (by example)

  • Anatomy of a scope
  • First-order functions
  • Free variables
  • High-order functions (bonus)
slide-7
SLIDE 7

Anatomy of a scope

  • What’s the point of a scope (e.g., block scope)?
slide-8
SLIDE 8

Anatomy of a scope

  • Recall our previous example:



 let y = 1;
 let z = 0;
 z++; 
 console.log(z);

  • In this model, we associate an environment (activation

record) with the code we’re executing

➤ Environment contains entries of all variables in scope ➤ Environment/stack ptr: points to cur activation record

environment ptr

slide-9
SLIDE 9

Anatomy of a scope

  • Recall our previous example:



 let y = 1;
 let z = 0;
 z++; 
 console.log(z);

  • In this model, we associate an environment (activation

record) with the code we’re executing

➤ Environment contains entries of all variables in scope ➤ Environment/stack ptr: points to cur activation record

environment ptr y 1 z

slide-10
SLIDE 10

Anatomy of a scope

  • In the environment model, we can distinguish between

values and locations

➤ r-values: plain old values; we can reason about them

using substitution semantics

➤ l-values: refer to locations where r-values are stored;

they persist beyond single expressions.

  • Why is this important?

➤ It tells us the kind of values operators like ++ must

  • take. A: r-values. B: l-values
slide-11
SLIDE 11

Anatomy of a scope

  • What’s the process for executing z++:



 let y = 1;
 let z = 0;
 z++; 
 console.log(z);

  • Algorithm:

➤ Find the current environment ➤ Check to see if variable being reference is in env: if

so, mutate!

y 1 z environment ptr

slide-12
SLIDE 12

Anatomy of a scope

  • What’s the process for executing console.log(z)



 let y = 1;
 let z = 0;
 z++; 
 console.log(z);

  • Algorithm:

➤ Find the current environment ➤ Check to see if variable being reference is in env: if

so, read it!

y 1 z 1 environment ptr

slide-13
SLIDE 13

Anatomy of a scope

  • This sounds slow!

➤ It is! ➤ But remember: this is not the machine model, this is

still an abstract model!

  • Not too far off from machine model

➤ In x86, you dereference %esp to figure out where

stack is and use offset to that location

➤ In JavaScript, you often do table lookup to find

location of variables

slide-14
SLIDE 14

The environment model (by example)

  • Anatomy of a scope ✓
  • First-order functions
  • Free variables
  • High-order functions (bonus)
slide-15
SLIDE 15

First-order functions

  • Consider activation record when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • What else do we need to keep track of?

environment ptr global env

slide-16
SLIDE 16

First-order functions

  • Consider activation record when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • What else do we need to keep track of?

control ret n 3 environment ptr global env

slide-17
SLIDE 17

More bookkeeping

  • The parts of an activation record when calling function

➤ control link: records where to switch the environment

pointer to when we finish evaluating in this scope.

➤ Do we need this for block scopes too? A: yes, B:no ➤ return value: l-value where the return value of

function should be stored

➤ parameters: l-value for each formal parameter ➤ local variables: l-values for each let+const declaration

slide-18
SLIDE 18
  • Anything else?

➤ Yes! Typically activation records will store the return

address where to resume ode execution — we’ll talk about this in the control flow lecture

More bookkeeping

slide-19
SLIDE 19

Let’s look at how evaluation works

  • Consider activation records when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • Do we keep the activation records

  • n the stack after evaluation?


A: yes, B: no
 


global env environment ptr control ret n 3

slide-20
SLIDE 20

Let’s look at how evaluation works

  • Consider activation records when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • Do we keep the activation records

  • n the stack after evaluation?


A: yes, B: no
 


global env environment ptr control ret n 3 control ret n 2

slide-21
SLIDE 21

Let’s look at how evaluation works

  • Consider activation records when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • Do we keep the activation records

  • n the stack after evaluation?


A: yes, B: no
 


global env environment ptr control ret n 3 control ret n 2 control ret n 1

slide-22
SLIDE 22

Let’s look at how evaluation works

  • Consider activation records when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • Do we keep the activation records

  • n the stack after evaluation?


A: yes, B: no
 


global env environment ptr control ret n 3 control ret n 2 control ret 1 n 1

slide-23
SLIDE 23

Let’s look at how evaluation works

  • Consider activation records when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • Do we keep the activation records

  • n the stack after evaluation?


A: yes, B: no
 


global env environment ptr control ret n 3 control ret 2*1 n 2 control ret 1 n 1

slide-24
SLIDE 24

Let’s look at how evaluation works

  • Consider activation records when calling function:


function fact(n) {
 if (n <= 1) {
 return 1;
 } else {
 return n * fact(n-1);
 }
 }
 fact(3);

  • Do we keep the activation records

  • n the stack after evaluation?


A: yes, B: no
 


global env environment ptr control ret 3*2*1 n 3 control ret 2*1 n 2 control ret 1 n 1

slide-25
SLIDE 25

The environment model (by example)

  • Anatomy of a scope ✓
  • First-order functions ✓
  • Free variables
  • High-order functions (bonus)
slide-26
SLIDE 26

Free variables

  • Consider activation records when calling f:


let x = 1;
 function f() {
 console.log(x)
 }
 f();

  • Should we lookup x via the control link?

➤ A: yes ➤ B: no

control ret environment ptr x 1

slide-27
SLIDE 27

Free variables

  • Consider activation records when calling g:


let x = 1;
 function f() {
 console.log(x)
 }
 
 function g() {
 let x = 2;
 f();
 }
 
 g();

  • What happens when we follow the control link?

control ret x 2 environment ptr x 1 control ret

g() f()

slide-28
SLIDE 28

Congrats, you did it!

You invented dynamic scoping!

slide-29
SLIDE 29

How do we “fix” this?

  • We need more bookkeeping!

➤ access link: reference to activation record of closest

enclosing lexical scope

  • Modify our lookup algorithm:

➤ Find the current environment ➤ Check to see if variable being reference is in env ➤ If not, follow the access link and repeat

slide-30
SLIDE 30

Retry with access links

  • Consider activation records when calling g:


let x = 1;
 function f() {
 console.log(x)
 }
 
 function g() {
 let x = 2;
 f();
 }
 
 g();
 
 


x 1 environment ptr

slide-31
SLIDE 31

Retry with access links

  • Consider activation records when calling g:


let x = 1;
 function f() {
 console.log(x)
 }
 
 function g() {
 let x = 2;
 f();
 }
 
 g();
 
 


x 1 control access x 2 environment ptr

g()

slide-32
SLIDE 32

Retry with access links

  • Consider activation records when calling g:


let x = 1;
 function f() {
 console.log(x)
 }
 
 function g() {
 let x = 2;
 f();
 }
 
 g();
 
 


x 1 control access x 2 environment ptr control access

g() f()

slide-33
SLIDE 33

Wait, there is some magic here

  • How do we know how to wire up the access links?


let x = 1;
 function f() {
 console.log(x)
 }
 
 function g() {
 let x = 2;
 f();
 }
 
 g();
 
 


x 1 control access x 2 environment ptr control access

g() f()

slide-34
SLIDE 34

Functions are data!

The act of defining a function should include the act of recording the access link associated with the function

slide-35
SLIDE 35

Treating functions as data

  • Let’s look at the example again, with minor rewrite


let x = 1;
 let f = () => {
 console.log(x)
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();

  • Function as data = closures = (current env ptr, code pointer)

x f g environment ptr

slide-36
SLIDE 36

Treating functions as data

  • Let’s look at the example again, with minor rewrite


let x = 1;
 let f = () => {
 console.log(x)
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();

  • Function as data = closures = (current env ptr, code pointer)

x 1 f g environment ptr

slide-37
SLIDE 37

Treating functions as data

  • Let’s look at the example again, with minor rewrite


let x = 1;
 let f = () => {
 console.log(x)
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();

  • Function as data = closures = (current env ptr, code pointer)

x 1 f g environment ptr

slide-38
SLIDE 38

Treating functions as data

  • Let’s look at the example again, with minor rewrite


let x = 1;
 let f = () => {
 console.log(x)
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();

  • Function as data = closures = (current env ptr, code pointer)

x 1 f g environment ptr

slide-39
SLIDE 39

Treating functions as data

  • When we evaluate function, the access link is set to

the pointer in the closure
 


let x = 1;
 let f = () => {
 console.log(x)
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();
 


x 1 f g environment ptr

♨ ♨

slide-40
SLIDE 40

Treating functions as data

  • When we evaluate function, the access link is set to

the pointer in the closure
 


let x = 1;
 let f = () => {
 console.log(x)
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();
 


x 1 f g environment ptr

♨ ♨

control access x 2

g()

slide-41
SLIDE 41

Treating functions as data

  • When we evaluate function, the access link is set to

the pointer in the closure
 


let x = 1;
 let f = () => {
 console.log(x)
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();
 


x 1 f g environment ptr

♨ ♨

control access x 2 control access

g() f()

slide-42
SLIDE 42

Treating functions as data

  • When we evaluate function, the access link is set to

the pointer in the closure
 


let x = 1;
 let f = () => {
 console.log(x) // 1
 }
 
 let g = () => {
 let x = 2;
 f();
 }
 
 g();
 


x 1 f g environment ptr

♨ ♨

control access x 2 control access

g() f()

slide-43
SLIDE 43

Closures

environment code

slide-44
SLIDE 44

The environment model (by example)

  • Anatomy of a scope ✓
  • First-order functions ✓
  • Free variables ✓
  • High-order functions (bonus)
slide-45
SLIDE 45

Higher-order functions

  • Consider the use of high-order mkCounter function



 function mkCounter(c) {
 return () => { 
 return c++;
 };
 }
 
 let x = mkCounter(0);
 let y = mkCounter(2);
 console.log(x());
 
 
 
 
 
 


x y env

slide-46
SLIDE 46

Higher-order functions

  • Consider the use of high-order mkCounter function



 function mkCounter(c) {
 return () => { 
 return c++;
 };
 }
 
 let x = mkCounter(0);
 let y = mkCounter(2);
 console.log(x());
 
 
 
 
 
 


x y control access c

env

slide-47
SLIDE 47

Higher-order functions

  • Consider the use of high-order mkCounter function



 function mkCounter(c) {
 return () => { 
 return c++;
 };
 }
 
 let x = mkCounter(0);
 let y = mkCounter(2);
 console.log(x());
 
 
 
 
 
 


x y control access c

env

slide-48
SLIDE 48

Higher-order functions

  • Consider the use of high-order mkCounter function



 function mkCounter(c) {
 return () => { 
 return c++;
 };
 }
 
 let x = mkCounter(0);
 let y = mkCounter(2);
 console.log(x());
 
 
 
 
 
 


x y control access c

control access c 2

env

slide-49
SLIDE 49

Higher-order functions

  • Consider the use of high-order mkCounter function



 function mkCounter(c) {
 return () => { 
 return c++;
 };
 }
 
 let x = mkCounter(0);
 let y = mkCounter(2);
 console.log(x());
 
 
 
 
 
 


x y control access c

control access c 2

env

slide-50
SLIDE 50

Higher-order functions

  • Consider the use of high-order mkCounter function



 function mkCounter(c) {
 return () => { 
 return c++;
 };
 }
 
 let x = mkCounter(0);
 let y = mkCounter(2);
 console.log(x());
 
 
 
 
 
 


x y control access c

control access c 2

env control access

slide-51
SLIDE 51

Higher-order functions

  • Consider the use of high-order mkCounter function



 function mkCounter(c) {
 return () => { 
 return c++;
 };
 }
 
 let x = mkCounter(0);
 let y = mkCounter(2);
 console.log(x());
 
 
 
 
 
 


x y control access c 1

control access c 2

env control access

slide-52
SLIDE 52

The environment model (by example)

  • Anatomy of a scope ✓
  • First-order functions ✓
  • Free variables ✓
  • High-order functions (bonus) ✓