towards dependent types for javascript

44
Towards Dependent Types for JavaScript Ravi Chugh , David Herman, Ranjit Jhala University of California, San Diego Mozilla Research

Upload: bevis

Post on 22-Mar-2016

39 views

Category:

Documents


0 download

DESCRIPTION

Towards Dependent Types for JavaScript. Ravi Chugh , David Herman, Ranjit Jhala. University of California, San Diego Mozilla Research. Towards Dependent Types for JavaScript. Explicit. A Large Subset of. Decidable. Features Common to All Editions. Outline. Challenges Our Approach - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Towards Dependent Types for JavaScript

Towards Dependent Types for JavaScript

Ravi Chugh, David Herman, Ranjit Jhala

University of California, San DiegoMozilla Research

Page 2: Towards Dependent Types for JavaScript

Towards Dependent Types for JavaScript

A Large Subset ofExplicit

Decidable

Features Common to All Editions

Page 3: Towards Dependent Types for JavaScript

3

Challenges

Our Approach

Preliminary Results

Outline

Page 4: Towards Dependent Types for JavaScript

4

Challenge 1: Reflection

function negate(x) { if (typeof x == “number”) return 0 - x else return !x}

x should be “num-or-bool”

Page 5: Towards Dependent Types for JavaScript

5

Challenge 2: Mutation

function negate(x) { if (typeof x == “number”) x = 0 - x else x = !x return x}

Different types stored in x

Page 6: Towards Dependent Types for JavaScript

6

Challenge 3: Coercions

3 + 4 // 7

“3” + “4” // “34”

3 + “4” // “34”

Page 7: Towards Dependent Types for JavaScript

7

Challenge 3: Coercions

!true // false

!1 // false

!“” // true

Page 8: Towards Dependent Types for JavaScript

8

Challenge 3: Coercions

0 === 0 // true

0 === “” // false

0 == “” // true

Page 9: Towards Dependent Types for JavaScript

9

Challenge 4: Objects

var par = {}var child = Obj.create(par)child.f = 1

var g = “g”child[g] = 2child.g // 2

child.h // undefinedpar.h = 3child.h // 3

Mutable

Dynamic Keys

Prototypes

Page 10: Towards Dependent Types for JavaScript

10

Challenge 5: Arrays

var nums = [0,1,2]nums[0] + nums[1] + nums[2]

delete nums[1]

for (i=0; i < nums.length; i++) sum += nums[i]

nums.push(42)

Finite or Unknown “Length”

“Packed” or “Unpacked”

Prototype-based

Page 11: Towards Dependent Types for JavaScript

occurrence types

∨, ∧F≤

Coq

refinement types

syntactic types dependent types

Expressivity

Usability

Prior Approaches

The JS Wall

Page 12: Towards Dependent Types for JavaScript

12

Outline

Challenges

Our Approach

Preliminary Results

Page 13: Towards Dependent Types for JavaScript

occurrence types

∨, ∧F≤

Coq

refinement types

syntactic types dependent types

Expressivity

Usability

Our Approach

The JS Wall

+ nesting

System D[POPL ’12]

+this talk

DependentJavaScript

[in submission]

Page 14: Towards Dependent Types for JavaScript

14

Refinement Types{x|p}

“value x such that formula p is true”{b|tag(b)=“boolean”}Bool {n|tag(n)=“number”}Num

{i|tag(i)=“number”integer(i)}Int

{x|true}Any

Page 15: Towards Dependent Types for JavaScript

15

Refinement Types{x|p}

“value x such that formula p is true”Num3 ::

Int3 ::

{i|i>0}3 ::

{i|i=3}3 ::

Page 16: Towards Dependent Types for JavaScript

16

Subtyping is Implication

{i|i=3} <: {i|i>0} <: Int <: Num

i=3i>0tag(i)=“number”integer(i)tag(i)=“number”

Page 17: Towards Dependent Types for JavaScript

17

Subtyping is Implication

LogicalSolver

AnnotatedProgram

TypeChecker

Page 18: Towards Dependent Types for JavaScript

18

System D [POPL 2012]var obj = { “n”: 17, “f”: function (i) { return i + 5 }}

{d|tag(d)=“Dict” tag(sel(d,“n”))=“number” sel(d,“f”)::Int Int }

obj ::

McCarthy’s decidable theory of arrays Great for dictionaries

of base values

Page 19: Towards Dependent Types for JavaScript

19

System D [POPL 2012]var obj = { “n”: 17, “f”: function (i) { return i + 5 }}

{d|tag(d)=“Dict” tag(sel(d,“n”))=“number” sel(d,“f”)::Int Int }

obj ::

Uninterpreted“has-type” predicate

Type constructors in formulas

Subtyping algorithm retains precision and decidability

Page 20: Towards Dependent Types for JavaScript

System D [POPL 2012]

Dependent JavaScript (DJS)photo courtesy of ClipArt ETC

Page 21: Towards Dependent Types for JavaScript

System D [POPL 2012]+ Types for JS Primitives+ Strong Updates+ Prototype Inheritance+ Arrays

Dependent JavaScript (DJS)

Page 22: Towards Dependent Types for JavaScript

System D [POPL 2012]+ Types for JS Primitives+ Strong Updates+ Prototype Inheritance+ Arrays

Dependent JavaScript (DJS)

Page 23: Towards Dependent Types for JavaScript

+ Types for JS Primitives+ Strong Updates+ Prototype Inheritance+ Arrays

Primitives Strong Updates Prototypes Arrays

Page 24: Towards Dependent Types for JavaScript

24

! :: Bool Boolalsethen b=trueelse b=false}

Primitives Strong Updates Prototypes Arrays

Choose degree ofprecision and coercion

Page 25: Towards Dependent Types for JavaScript

25

! :: x:Bool {b|if x=falsethen b=trueelse b=false}

Primitives Strong Updates Prototypes Arrays

Choose degree ofprecision and coercion

Page 26: Towards Dependent Types for JavaScript

26

! :: x:Any {b|if falsy(x)then b=trueelse b=false}

x=falsex=0x=nullx=“”x=undefinedx=NaN

falsy(x)

Choose degree ofprecision and coercion

Primitives Strong Updates Prototypes Arrays

Page 27: Towards Dependent Types for JavaScript

27

function negate(x) { if (typeof x == “number”) x = 0 - x else x = !x return x}

NumOrBool NumOrBoolx:NumOrBool {y|tag(y)=tag(x)}

PathSensitive

FlowSensitive

Strong UpdatesPrimitives Prototypes Arrays

(even with ordinary refinement types)

Page 28: Towards Dependent Types for JavaScript

28

PrototypesPrimitives Strong Updates Arrays

var grandpa = …, parent = Object.create(grandpa), child = Object.create(parent), b = k in child,

{v|v=true iff

(has(child,k)

(has(parent,k)

(has(grandpa,k)

(HeapHas(H,great,k))}

grandpa

child

parent

Key Membership via Prototype Chain

Unrolling

b ::

H (Rest of Heap)

great

Page 29: Towards Dependent Types for JavaScript

PrototypesPrimitives Strong Updates Arrays

var grandpa = …, parent = Object.create(grandpa), child = Object.create(parent), b = k in child, x = child[k]

{v|if has(child,k) then v=sel(child,k)

{v|elif has(parent,k) then v=sel(parent,k)

{v|elif has(grandpa,k) then v=sel(grandpa,k)

{v|elif HeapHas(H,great,k)) then v=HeapSel(H,great,k))

{v|else v=undefined}

Key Lookup viaPrototype Chain

Unrolling

x ::

Page 30: Towards Dependent Types for JavaScript

30

PrototypesPrimitives Strong Updates Arrays

Key Idea

Reduce prototype semanticsto decidable theory of arrays

via flow-sensitivity and unrolling

Page 31: Towards Dependent Types for JavaScript

ArraysPrimitives Strong Updates Prototypes

Track types, “packedness,” and lengthof arrays where possible

{a|a::Arr(T){a|packed(a){a|len(a)=10}

X T T T T… X ……

T? T? T? T? T?… T? ……

T? {x|T(x)x=undefined}

-1 0 1 2 len(a)

X {x|x=undefined}

Page 32: Towards Dependent Types for JavaScript

32

ArraysPrimitives Strong Updates Prototypes

Encode tuples as arrays

{a|a::Arr(Any){a|packed(a)len(a)=2

{a|Int(sel(a,0)){a|Str(sel(a,1))}

var tup = [17, “ni hao”]

Page 33: Towards Dependent Types for JavaScript

33

ArraysPrimitives Strong Updates Prototypes

{a|a::Arr(Any){a|packed(a)len(a)=3

{a|…}

var tup = [17, “ni hao”] tup.push(true) a

Re-use prototype mechanism

Page 34: Towards Dependent Types for JavaScript

34

Recap of DJS Tricks

Uninterpreted Functions

Flow Sensitivity

Prototype Unrolling

Refinement Type Encodings

Page 35: Towards Dependent Types for JavaScript

35

Outline

Challenges

Our Approach

Preliminary Results

Page 36: Towards Dependent Types for JavaScript

DesugaredProgram

Z3 SMTSolver

TypeChecker

DJSProgram

DesugarerBased on Guha et al.

[ECOOP ’10]

~6 KLOC OCaml

Implementation

Page 37: Towards Dependent Types for JavaScript

DesugaredProgram

Z3 SMTSolver

TypeChecker

DJSProgram

DesugarerBased on Guha et al.

[ECOOP ’10]

Mainly SunSpider and JSGP

300 Unannotated LOC70% Annotation overhead

9 Benchmarks run in <3s4 Benchmarks run in 8-52s

Benchmarks

Page 38: Towards Dependent Types for JavaScript

DesugaredProgram

Z3 SMTSolver

TypeChecker

DJSProgram

DesugarerBased on Guha et al.

[ECOOP ’10]

All parts of type system used

Can optimize patternsduring desugaring

Can optimize patternsduring type checking

Evaluation

Page 39: Towards Dependent Types for JavaScript

39

Conclusion

DJS is a steptowards climbing

the JS Wall

Page 40: Towards Dependent Types for JavaScript

40

Thanks!

ravichugh.com/nested

D::github.com/ravichugh/djs

Page 41: Towards Dependent Types for JavaScript

41

/*: x:NumOrBool {ite Num(x) Num(v) Bool(v)} */function negate(x) { x = (typeof x == “number”) ? 0 – x : !x return x}

/*: x:Any {v iff falsy(x)} */function negate(x) { x = (typeof x == “number”) ? 0 – x : !x return x}

{p} {v|p}

Page 42: Towards Dependent Types for JavaScript

42

ObjHas(d,k,H,d’) has(d,k)HeapHas(H,d’,k)

/*: x:Ref / [x |-> d:Dict |> ^x] {v iff ObjHas(d,”f”,curHeap,^x)} / sameHeap */function hasF(x) { return “f” in x}

x:T1/H1T2/H2

Function Types and Objects

output typeinput heapinput type output heap

Page 43: Towards Dependent Types for JavaScript

43

ObjSel(d,k,H,d’) ite has(d,k) sel(d,k) HeapSel(H,d’,k)

x:T1/H1T2/H2

Function Types and Objects

output typeinput heapinput type output heap

/*: x:Ref / [x |-> d:Dict |> ^x] {v=ObjSel(d,”f”,curHeap,^x)} / sameHeap */function readF(x) { return x.f}

Page 44: Towards Dependent Types for JavaScript

44

Q: What is “Duck Typing”?

Structural Object Types+

Logical Reasoning ?