/
A Fix for Dynamic Scope A Fix for Dynamic Scope

A Fix for Dynamic Scope - PowerPoint Presentation

mitsue-stanley
mitsue-stanley . @mitsue-stanley
Follow
380 views
Uploaded On 2017-04-23

A Fix for Dynamic Scope - PPT Presentation

Ravi Chugh U of California San Diego Backstory 2 Goal Types for Dynamic Languages Core λ Calculus Extensions Syntax and Semantics of JavaScript Translation à la Guha et al ID: 540587

tock tick fact int tick tock int fact str ref open types function inlet examples calculus fix dyn return

Share:

Link:

Embed:

Download Presentation from below link

Download Presentation The PPT/PDF document "A Fix for Dynamic Scope" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.


Presentation Transcript

Slide1

A Fix for Dynamic Scope

Ravi Chugh

U. of California, San DiegoSlide2

Backstory

2

Goal: Types for “Dynamic” Languages

Core

λ

-Calculus

+ Extensions

Syntax and Semantics

of JavaScript

Translation à la Guha et al.

(ECOOP 2010)Slide3

Backstory

3

Goal: Types for “Dynamic” Languages

Core

λ

-Calculus

+ Extensions

Approach: Type Check Desugared Programs

Simple

Imperative

,

RecursiveFunctions are Difficult to VerifySlide4

4

Translate to statically typed calculus?

var

fact

=

function

(n

)

{ if

(n <=

1)

{

return

1

;

}

else {

return

n * fact(n-1); }};Slide5

let

fact

=

λ

n

. if n

<=

1 then 1

else n * fact

(n

-

1

)

Option 1:

λ

-Calculus (

λ

)

5

Translate to statically typed calculus?

var

fact = function(n) { if

(

n

<= 1)

{

return 1; } else { return n * fact(n-1); }};

fact

is not bound yet…

✗Slide6

let

fact

=

fix

(

λ

fact. λn.

if n

<= 1 then 1

else n

*

fact

(

n

-

1

)

)

Desugared

fact

should be mutable…

Option 2: λ-Calculus + Fix (λfix)6

Translate to statically typed calculus?

var

fact = function(n

)

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

n

-

1); }

};

✗Slide7

let

fact

=

ref

(

fix

(λfact. λ

n

. if

n <= 1

then 1

else

n

*

fact

(

n

-

1

)

))

Recursive call doesn’t go through reference…

Okay here, but prevents mutual recursion Option 3: λ-Calculus + Fix + Refs (λfix,ref)

7

Translate to statically typed calculus?

var

fact = function(n

) { if (n <= 1) { return 1; } else { return n

*

fact

(n-1)

; }

};

✗Slide8

let

fact

=

ref

(

λ

n. if n

<= 1 then

1 else n *

!fact(

n

-

1

)

)

Yes, this captures the semantics!

But how to type check ???

Option 4:

λ

-Calculus

+ Fix

+ Refs (λref)8Translate to statically typed calculus?

var

fact = function(n

)

{

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

-1)

;

}};

✓Slide9

let

fact

=

ref

(

λ

n. if n

<= 1 then

1 else n *

!fact(

n

-

1

)

)

9Slide10

10

let

fact

=

ref

(

λn. 0) in

fact

:= λn

. if n

<= 1

then

1

else

n

*

!fact

(

n

-

1

)

;Backpatching Pattern in λreffact :: Ref (Int  Int)

Assignment

relies on

and

guarantees

the reference invariantSlide11

11

let

fact = ref

(

λ

n

. 0) infact :=

λ

n. if

n <= 1 then 1 else n * !fact

(n

-

1)

;

Backpatching Pattern in

λ

ref

But we want to

avoid

initializers to:

Facilitate JavaScript translation

Have some fun!

Simple types suffice if reference isinitialized with dummy function…Slide12

Proposal:

Open Types

for

λ

ref

12

let

fact =

ref

(λn

. if

n <=

1

then

1

else

n

*

!fact

(

n

-

1

))fact :: (fact :: Ref (Int

Int

))

Ref (Int  Int) Assuming fact points to an integer function,fact points to an integer functionSlide13

Proposal: Open Types

for

λ

ref

13

let

fact

= ref (λn.

if n

<= 1 then

1 else n

*

!fact

(

n

-

1

)

)

in

!fact

(

5)fact :: (fact :: Ref (Int  Int)) 

Ref (Int

Int

)

Assuming fact points to an integer function,fact points to an integer functionType system must checkassumptions at every dereferenceSlide14

Proposal: Open Types

for

λ

ref14

let

fact = ref (λn

.

if n

<= 1 then

1 else

n

*

!fact

(

n

-

1

)

)

Motivated by

λ

ref programs that result fromdesugaring JavaScript programs Slide15

Proposal: Open Types

for

λ

ref15

Motivated by

λ

ref programs that result from desugaring JavaScript programs let

fact

= λ

n. if

n

<=

1

then

1

else

n

*

fact

(

n

-

1)Proposal also applies to, and is easier to show for,the dynamically-scoped λ-calculus (λdyn)

Bound at the time of call…

No need for fix or references Slide16

Lexical

vs.

Dynamic

Scope

16

λ

Environment at definition is frozen in closure…

And is used to evaluate function body

Explicit evaluation rule for recursionSlide17

λ

dyn

Lexical

vs.

Dynamic

Scope

17

λ

Bare lambdas, so

all

free variables resolved in calling environmentSlide18

λ

dyn

Lexical

vs.

Dynamic

Scope

18

λ

No need for

fix constructSlide19

Open Types for

λ

dyn

19

Types (Base or Arrow)

Open Types

Type Environments

Open Type EnvironmentsSlide20

Open Types for

λ

dyn

20

Open Typing

Open function type describes environment for function bodySlide21

Open Types for

λ

dyn

21

Open Typing

Open function type describes environment for function body

Type environment at function definition is

irrelevantSlide22

Open Types for

λ

dyn

22

Open Typing

STLC + Fix

In some sense, extreme generalization of [T-Fix]Slide23

Open Types for

λ

dyn

23

Open Typing

STLC + FixSlide24

Open Types

for

λ

dyn

24

Open Typing

For every

Rely-set

contains

Guarantee-set

contains

(most recent, if multiple)Slide25

Open Types for

λ

dyn

25

Open Typing

Open Typing

For every

Rely-set

contains

Guarantee-set

contains

(most recent, if multiple)

Discharge all assumptionsSlide26

Open Types for

λ

dyn

26

Open TypingSlide27

Examples

27

let

fact

=

λn. if

n

<= 1

then 1 else

n *

fact

(

n

-

1

)

in

fact 5

fact

:: (

fact

:: Int  Int)  Int  Int Slide28

Examples

28

let

fact =

λ

n

.

if

n <= 1 then 1

else n * fact(

n-

1)

in

fact 5

Guarantee

Rely

fact

:: (

fact

:: Int

Int

)

Int

Int

✓Slide29

Error: var [tock] not found

Examples

29

let

tick n

=

if

n

>

0

then

“tick ”

++

tock n

else

“”

in

tick 2

;Slide30

Examples

30

let

tick n

=

if n >

0

then “tick ” ++

tock n else

“” in

tick 2

;

tick

:: (

tock

:: Int

Str

)

Int  Str Slide31

Examples

31

let

tick n =

if

n > 0 then “tick ” ++ tock n else “” in

tick 2

;

Guarantee

Rely

tick

:: (

tock

:: Int

Str

)

Int

Str ✗Slide32

“tick tock tick tock ”

Examples

32

let

tick n

=

if

n

>

0

then

“tick ”

++

tock n

else

“”

in

let

tock n

= “tock ” ++ tick (n-1) intick 2

;Slide33

Examples

33

let

tick n

=

if n >

0

then “tick ” ++

tock n else

“” in

let

tock n

=

“tock ”

++

tick

(

n

-

1

) intick 2;tick :: (tock :: Int  Str)  Int

Str

tock

:: (

tick :: Int  Str)  Int  Str Slide34

Examples

34

let

tick n =

if

n > 0 then “tick ” ++ tock n else “” in

let tock n =

“tock ” ++ tick (

n-1) intick 2

;

tick

:: (

tock

:: Int

Str

)

Int

Str

tock

:: (

tick

:: Int

Str)  Int  Str GuaranteeRely✓Slide35

Error: “bad” not a function

Examples

35

let

tick n

=

if

n

>

0

then

“tick ”

++

tock n

else

“”

in

let

tock n

= “tock ” ++ tick (n-1) inlet

tock

=

“bad”

in

tick 2;Slide36

Examples

36

let

tick n

=

if n >

0

then “tick ” ++

tock n else

“” in

let

tock n

=

“tock ”

++

tick

(

n

-

1

) inlet tock = “bad” in tick 2;

tock

::

Str

tick :: (tock :: Int  Str)  Int  Str tock :: (tick :: Int 

Str)

Int  Str Slide37

Examples

37

let

tick n =

if

n

> 0 then “tick ” ++ tock n

else “” in

let tock n = “tock ” ++ tick

(n

-

1) in

let tock =

“bad”

in

tick 2

;

Guarantee

Rely

tock

::

Str

tick

:: (

tock

:: Int

 Str)  Int  Str tock :: (tick :: Int  Str) 

Int

Str ✗Slide38

“tick tick ”

Examples

38

let

tick n

=

if

n

>

0

then

“tick ”

++

tock n

else

“”

in

let

tock n

= “tock ” ++ tick (n-1) inlet

tock

=

tick

(

n

-1) in tick 2;Slide39

Examples

39

let

tick n

=

if n >

0

then “tick ” ++

tock n else

“” in

let

tock n

=

“tock ”

++

tick

(

n

-

1

) inlet tock = tick (n-1) in

tick 2

;

tick

:: (

tock

:: Int  Str)  Int  Str tock :: (tick :: Int  Str) 

Int 

Str

tock :: (tick :: Int

Str

)

Int

Str

Slide40

Examples

40

let

tick n =

if

n > 0 then “tick ” ++ tock n else “” in

let tock n =

“tock ” ++ tick (

n-1) inlet tock =

tick (

n

-

1) in

tick 2

;

Guarantee

Rely

tick

:: (

tock

:: Int

Str

)

Int  Str tock :: (tick :: Int  Str) 

Int

Str ✓

tock

:: (

tick

:: Int

Str

)

Int

Str

Slide41

Recap

41

Open Types capture

“late packaging”

of recursive definitions in

dynamically-scoped

languages

(Metatheory has not yet been worked)Several potential applications in

lexically-scoped languages…Slide42

Open Types for λ

ref

42

For open types in this setting,

type system must support

strong updates

to mutable variablese.g. Thiemann et al. (ECOOP 2010), Chugh et al. (OOPSLA 2012)References

in

λref are similar to

dynamically-scoped bindings in λdynSlide43

Open Types for λ

ref

43

let

tick =

ref null inlet tock

=

ref null intick

:= λn

.

if

n

>

0

then

“tick ”

++

!tock

(

n

) else “”;tock := λn.

“tock ”

++

!tick

(

n

-1);!tick(2);tick :: (tock :: Ref (Int  Str)) 

Ref (Int 

Str

)tock :: (tick

:: Ref (Int  Str

))

Ref (Int

Str

)

tick

:: Ref Null

tick

:: Ref Null

tock

:: Ref Null

tick

:: (

tock

:: Ref (Int

Str

))

Ref (Int

Str

)

tock

:: Ref Null

Guarantee

Rely

tick

:: (

tock

:: Ref (Int

Str

))

Ref (Int

Str

)

tock

:: (

tick

:: Ref (Int

Str

))

Ref (Int

Str

)

Slide44

Open Types for Methods

44

let

tick n

=

if n >

0

then “tick ” ++

this.tock(

n)

else

“”

in

let

tock n

=

“tock ”

++

this

.

tick(n-1) inlet obj = {tick=tick

;

tock

=

tock

} in

obj.tick(2);tick :: (this :: {tock: Int  Str})  Int 

Str

tock

:: (this

:: {tick: Int 

Str

}

)

Int

Str

Slide45

Related Work

Dynamic scope in lexical settings for:

Software updates

Dynamic code loading

Global flagsImplicit Parameters of Lewis et al. (POPL 2000)Open types mechanism resembles their approachWe aim to support recursion and referencesOther related work

Bierman et al. (ICFP 2003)Dami (TCS 1998), Harper (Practical Foundations for PL)

…45Slide46

Thanks!

46

Thoughts? Questions?

Open Types for Checking Recursion in

:

Dynamically-scoped

λ-calculus

Lexically-scoped λ-calculus with referencesSlide47

EXTRA SLIDES

47Slide48

Higher-Order Functions

48

Disallows function arguments with free variables

This restriction precludes “downwards funarg problem”

To be less restrictive:Slide49

-17

Partial Environment Consistency

49

let

negateInt

() =

0

-

x

in

let

negateBool

() =

not x

in

let

x

=

17

in

negateInt ();

negateInt

:: (

x

:: Int

)

 Unit  Int negateBool :: (x :: Bool)  Unit  Bool x :: Int

Safe at run-time

even though not all assumptions satisfiedSlide50

Partial Environment Consistency

50

To be less restrictive:

Only and

its transitive

dependencies in