Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

49
Nested Refinements: A Logic for Duck Typing Ravi Chugh , Pat Rondon, Ranjit Jhala (UCSD) ::
  • date post

    19-Dec-2015
  • Category

    Documents

  • view

    214
  • download

    1

Transcript of Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

Page 1: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

Nested Refinements:A Logic for Duck

Typing

Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD)

::

Page 2: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

2

“dictionary” = finite map from “keys” to values

“object” = mutable dictionary

JavaScript has “prototype” inheritance

record

Terminology

fields

properties

delegation

imperative

Page 3: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

3

Types for JavaScript: Approach

System !D

System D

lambdas

dictionaries

tag tests

mutation

prototypes

Guha et al. (ECOOP 2010)

Dependent JavaScript (DJS)

(POPL 2012)

(In Submission)

Dependent JavaScript (DJS)

Page 4: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

4

System D

lambdas

dictionaries

tag tests (POPL 2012)

{|tag()=“Int”tag()=“Bool”}x ::

{|tag()=“Dict” tag(sel(,“n”))=“Int”tag(sel(,m))=“Int”}

d ::

Functions inside dictionariesChallenge:All types as quantifier-free formulasApproach:

Page 5: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

5

Key Idea: Nested Refinements

{|tag()=“Dict”

sel(,f) ::

}

d ::

{|tag()=“Int” }

{|tag()=“Int” }

uninterpreted predicate“x :: U” says“x has-type U”

uninterpreted constantin the logic…

… but syntactic arrowin the type system

1 + d[f](0)

Page 6: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

6

• All values described by refinement formulasT ::= {|p}

• “Has-type” predicate for arrows in formulasp ::= … | x :: y:T1T2

• Can express several scripting idioms

• Automatic type checking– Decidable refinement logic

– Subtyping = SMT Validity + Syntactic Subtyping

Key Idea: Nested Refinements

Page 7: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

7

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

y:Top{| = tag(y)}typeof ::

{| :: }typeof :: y: {|true } {| = tag(y) }

y:{|true}{| = tag(y)}typeof ::

x:{|tag() = “number” tag() = “boolean”}

{|tag() = tag(x)}

x:IntOrBool{|tag() = tag(x)}

Page 8: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

8

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

{|Int()}x ::

{|Int()}0 - x ::

✓x:IntOrBool{|tag() = tag(x)}

Page 9: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

9

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

{|Bool()}x ::

{|Bool()}!x ::

✓x:IntOrBool{|tag() = tag(x)}

Page 10: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

10

function getCount (x,c) { if (c in x) { return toInt(x[c]); } else { return 0; }}

(x:Dict,c:Str)Int

{| = true has(x,c)}

safe dictionary key lookup

Page 11: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

11

function getCount (x,c) { if (c in x) { return toInt(x[c]); } else { return 0; }}

function incCount (x,c) { var i = getCount(x,c); return {x with c = i + 1};}

(x:Dict,c:Str)Int

(x:Dict,c:Str){|EqMod(,x,c) Int(d[c])}

tag(sel(d,c)) = “Int”

Page 12: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

12

T ::= {|p}

p ::= … | x :: U

U ::= y:T1T2 | A | List T | Null

Adding Type Constructors

Page 13: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

13

function apply (f,x) { return f(x); }

∀A,B. ({|:: {|:: A }{|:: B } }, {|:: A })

{|:: B }

∀A,B. ((AB), A) B

Page 14: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

14

function dispatch (d,f) { return d[f](d); }

∀A,B. (d:{| :: A }, {|d[] :: AB }) {| :: B }

d :: A but additional constraints on A

≈ ∀A <: {f: A B}. d :: A

a form of“bounded quantification”

Page 15: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

15

function map (f,xs) { if (xs == null) { return null; } else { return f(xs[“hd”]) :: map (f,xs[“tl”]); }}

∀A,B.

({|:: AB }, {|:: List[A] }) {|:: List[B] }

encode recursive data as dictionaries

∀A,B. ((AB), List[A]) List[B]

Page 16: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

16

function filter (f,xs) { if (xs == null) { return null; } else if (f(xs[“hd”])) { return xs[“hd”] :: filter(f,xs[“tl”]); } else { return filter(f,xs[“tl”]); }}

∀A,B. ((x:A{|n = true x:: B }), List[A])List[B]

usual definition,but an interesting type*

*Tobin Hochstadt and Felleisen (POPL 2008)

Page 17: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

17

System !D

System D

lambdas

dictionaries

tag tests

mutation

prototypes

Object.beget = function(o) { var F = function(o) { return this; }; F.prototype = o; return new F();}

Crockford (JavaScript: The Good Parts)

Page 18: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

18

var x = {};

x.f = 1;

var xf = x.f;

Strong Update à la Alias Types• Types are flow-insensitive (as usual)• But heap types are flow-sensitive

– Mappings from locations to types can change

18

{|:: Ref L }x ::

L :: d:{|=empty }

safe given the updated heap type

L :: d’: {|=upd(d,“f”,1)}

Page 19: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

19

Prototype Chain Unrolling

L1 :: dChild:

L2 :: dParent:

L3 :: dGrandpa:

{|:: Ref L3 }grandpa ::

{|:: Ref L2 }parent ::

{|:: Ref L1 }child ::

H = Rest of Heap

var granpda = …;

var parent = beget(grandpa);

var child = beget(parent);

T3

T1

T2

(k in child)

has(dChild,k)

has(dParent,k)

has(dGrandpa,k)

HeapHas(H,L4,k)

Page 20: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

Recap / Future Work

20

!D

D

lambdas

dictionaries

tag tests

mutation

prototypes

DJSApplications so far:

Inheritance patterns, JS: Good Parts

Future work:Microbenchmarks (e.g. SunSpider)

Libraries (e.g. Array.prototype)

Application to Browser Extensions

ES5/ES6 Features

Class-based Inheritance

More Local Type Inference

Page 21: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

21

Thanks!

Dravichugh.com/nested

::

Thanks to Brown PLT for the LambdaJS tools!

Page 22: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

22

Extra Slides

Page 23: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

23

Constants

tagof :: x:Top{| = tag(x)}

mem :: d:Dictk:Str {|Bool() = True has(d,k)}

get :: d:Dictk:{|Str() has(d,)}{| = sel(d,k)}

set :: d:Dictk:Strx:Top {| = upd(d,k,x)}

rem :: d:Dictk:Str{| = upd(d,k,bot)}

Page 24: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

24

• Types

• Formulas

• Logical Values

Macros{|tag()=“Int” }

Int

x:T1T2 {|:: }x:T1T2

tag(x) = “Str”Str(x)

sel(n,“k”)x.k

sel(n,k)x[k]

sel(d,k) != bothas(d,k)

∀k’. k’ != k sel(d,k) != sel(d’,k)

EqMod(d,d’,k)

Page 25: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

25

Ontolet onto callbacks f obj = if f = null then new List(obj,callbacks) else let cb = if tagof f = “Str” then obj[f] else f in new List(fun () -> cb obj, callbacks)

∀A. callbacks:List[TopTop]

f:{|Str():: ATop }

obj:{|:: A

(f=null :: AInt)

(Str(f) [f] :: AInt) }

List[TopTop]

onto ::

functional version of Dojo function

Page 26: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

26

Onto (2)let onto (callbacks,f,obj) = if f = null then new List(obj,callbacks) else let cb = if tagof f = “Str” then obj[f] else f in new List(fun () -> cb obj, callbacks)

callbacks:List[TopTop]

* f:{g|Str(g)g:: {x|x= obj}Top }

* obj:{o|(f=null o :: {x|x= o}Int)

(Str(f) o[f] :: {x|x= o}Int) }

List[TopTop]

onto ::

functional version of Dojo function

Page 27: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

27

Related Work• TODO

Page 28: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

28

Traditional vs. Nested Refinements

Page 29: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

29

• Reuse refinement type architecture

• Find a decidable refinement logic for– Tag-tests– Dictionaries– Lambdas

• Define nested refinement type architecture

Approach: Refinement Types

✗✓✓*

Page 30: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

30

Nested Refinements

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x :: U

• Refinement formulas over a decidable logic– uninterpreted functions, McCarthy arrays, linear arithmetic

• Only base values refined by formulasAll values

T ::= {|p} | x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | …

traditional refinements

Page 31: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

31

Nested Refinements

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

• Refinement formulas over a decidable logic– uninterpreted functions, McCarthy arrays, linear arithmetic

• Only base values refined by formulas• “has-type” allows “type terms” in formulas

All values

T ::= {|p} | x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | …

traditional refinements

Page 32: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

32

Nested Refinements

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

• Refinement formulas over a decidable logic– uninterpreted functions, McCarthy arrays, linear arithmetic

• Only base values refined by formulas• “has-type” allows “type terms” in formulas

All values

Page 33: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

33

Subtyping

Page 34: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

34

Subtyping

T ::= {|p} | x:T1T2

traditional refinements

Implication

SMT Solver

Subtyping

{|true }Top

tag()=“Int” true

{|tag()=“Int” }Int

Int <: Top

Page 35: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

35

Subtyping

T ::= {|p} | x:T1T2

traditional refinements

Implication

SMT Solver

Subtyping

{|true }Top

{|tag()=“Int” }Int

Top Int <: Int Int

Int <: Top Int <: Int

tag()=“Int” true

tag()=“Int” tag()=“Int”

Page 36: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

36

Subtyping

T ::= {|p} | x:T1T2

traditional refinements

Implication

SMT Solver

Subtyping

{|true }Top

{|tag()=“Int” }Int

Top Int <: Int Int

Int <: Top Int <: Int

tag()=“Int” true

tag()=“Int” tag()=“Int”

Arrow Rule

Page 37: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

37

Subtyping

T ::= {|p} | x:T1T2

traditional refinements

Implication

SMT Solver

Subtyping Arrow Rule

Decidable if:• Only values in formulas• Underlying theories decidable

With nested refinements:• No new theories• But implication is imprecise!

Page 38: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

38

Subtyping with Nesting

Implication

SMT Solver

Subtyping

Invalid, as these are distinctuninterpreted constants

:: Top Int :: Int Int✗

Page 39: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

39

Subtyping with Nesting

Implication

SMT Solver

Subtyping Arrow Rule

When goal is base predicate:p q

When goal is “has-type” predicate:p x :: U

Implication

SMT Solver

Subtyping

p x :: U’

U’ <: U

p q

Page 40: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

40

p :: Top Int

UninterpretedReasoning

Subtyping with Nesting

p :: Int Int

Normalize formulas tosubdivide obligations appropriately

Top Int <: Int Int

+ SyntacticReasoning

Page 41: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

41

Normalization• TODO

Page 42: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

42

foo example

Page 43: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

43

let foo f d = if tagof f = “Str” then d.n + d[f](0) else d.n + f(0)

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

f:{|Str():: IntInt }

d:{|Dict()

Int(.n)

Str(f) [f] :: IntInt }

Int

foo ::

Page 44: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

44

let foo f d = if tagof f = “Str” then d.n + d[f](0) else d.n + f(0)

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

f:{|Str():: IntInt }

d:{|Dict()

Int(.n)

Str(f) [f] :: IntInt }

Int

foo ::

Page 45: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

45

let foo f d = if tagof f = “Str” then d.n + d[f](0) else d.n + f(0)

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

f:{|Str():: IntInt }

d:{|Dict()

Int(.n)

Str(f) [f] :: IntInt }

Int

foo ::

tag() = “Str”

{|tag()=“Int” }

{|tag()=“Int” }

Page 46: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

46

let foo f d = if tagof f = “Str” then d.n + d[f](0) else d.n + f(0)

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

f:{|Str():: IntInt }

d:{|Dict()

Int(.n)

Str(f) [f] :: IntInt }

Int

foo ::

Page 47: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

47

let foo f d = if tagof f = “Str” then d.n + d[f](0) else d.n + f(0)

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

f:{|Str():: IntInt }

d:{|Dict()

Int(.n)

Str(f) [f] :: IntInt }

Int

foo ::

sel(n,“n”) sel(n,f)

Page 48: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

48

let foo f d = if tagof f = “Str” then d.n + d[f](0) else d.n + f(0)

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

f:{|Str():: IntInt }

d:{|Dict()

Int(.n)

Str(f) [f] :: IntInt }

Int

foo ::

Page 49: Nested Refinements: A Logic for Duck Typing Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) ::

49

{|::

}

{|::

} Int

d: {|tag()=“Dict”

tag(sel(,“n”))=“Int”

tag(f)=“Str”

sel(,f) :: }IntInt

f:{|tag()=“Str”:: }IntInt

let foo f d = if tagof f = “Str” then d.n + d[f](0) else d.n + f(0)

T ::= {|p}U ::= x:T1T2

p ::= pq | … | x = y | x < y | … | tag(x) = “Int” | … | sel(x,y) = z | … | x::U

foo ::