+ All Categories
Home > Documents > Nested Refinements: A Logic for Duck Typing

Nested Refinements: A Logic for Duck Typing

Date post: 05-Jan-2016
Category:
Upload: mliss
View: 45 times
Download: 7 times
Share this document with a friend
Description:
Nested Refinements: A Logic for Duck Typing. ::. Ravi Chugh , Pat Rondon, Ranjit Jhala (UCSD). What are “Dynamic Languages”?. tag tests. affect control flow. dictionary objects. indexed by arbitrary string keys. first-class functions. can appear inside objects. - PowerPoint PPT Presentation
Popular Tags:
52
Nested Refinements: A Logic for Duck Typing Ravi Chugh , Pat Rondon, Ranjit Jhala (UCSD) ::
Transcript
Page 1: Nested Refinements: A Logic for Duck Typing

Nested Refinements:A Logic for Duck

Typing

Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD)

::

Page 2: Nested Refinements: A Logic for Duck Typing

2

What are “Dynamic Languages”?

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)

tag tests affect control flow

dictionary objects indexed by arbitrary string keys

first-class functions can appear inside objects

Page 3: Nested Refinements: A Logic for Duck Typing

3

Problem: Lack of static types… makes rapid prototyping / multi-language applications easy

… makes reliability / performance / maintenance hard

This Talk: System D… a type system for these features

tag tests affect control flow

dictionary objects indexed by arbitrary string keys

first-class functions can appear inside objects

Page 4: Nested Refinements: A Logic for Duck Typing

occurrence types

∨, ∧

Our Approach: Quantifier-free formulas

tag tests affect control flow

dictionary objects indexed by arbitrary string keys

first-class functions can appear inside objects

Expressiveness

Usability

F≤

Coq

refinement types

nested refinements

syntactic approaches dependent approaches

1. increase expressiveness

2. retain level of automation

Page 5: Nested Refinements: A Logic for Duck Typing

5

Functions inside dictionariesChallenge:

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

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

d ::

tag tests affect control flow

dictionary objects indexed by arbitrary string keys

first-class functions can appear inside objects

Page 6: Nested Refinements: A Logic for Duck Typing

6

Key Idea: Nested Refinements

{|tag() = “Dict”

sel(,f) ::

}

d ::

{|tag()=“Int” }

{|tag()=“Int” }

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

syntactic arrow type…

1 + d[f](0)

Page 7: Nested Refinements: A Logic for Duck Typing

7

Key Idea: Nested Refinements

{|tag() = “Dict”

sel(,f) ::

}

d ::

{|tag()=“Int” }

{|tag()=“Int” }

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

1 + d[f](0)

syntactic arrow type…

… but uninterpreted constant in the logic

Page 8: Nested Refinements: A Logic for Duck Typing

8

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

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

• Can express idioms of dynamic languages

• Automatic type checking– Decidable refinement logic

– Subtyping = SMT Validity + Syntactic Subtyping

Key Idea: Nested Refinements

Page 9: Nested Refinements: A Logic for Duck Typing

Outline

Intro

Examples

Subtyping

Type Soundness

Conclusion

9

Page 10: Nested Refinements: A Logic for Duck Typing

10

let negate x = if tagof x = “Int” then 0 – x else not x

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

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

{|tag() = tag(x)}

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

y:{|true}

Page 11: Nested Refinements: A Logic for Duck Typing

11

IntOrBoolx ::Γ

{|Int()}x ::

{|Int()}0 - x ::

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

let negate x = if tagof x = “Int” then 0 – x else not x

tag(x) = “Int”

type environment

✓SMT Solver

Page 12: Nested Refinements: A Logic for Duck Typing

12

IntOrBoolx ::Γ

{|Bool()}x ::

{|Bool()}not x ::

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

let negate x = if tagof x = “Int” then 0 – x else not x

not (tag(x) = “Int”)

type environment

SMT Solver

✓✓

Page 13: Nested Refinements: A Logic for Duck Typing

13

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

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

Nesting structure hidden with syntactic sugar

Page 14: Nested Refinements: A Logic for Duck Typing

14

Dictionary Operations

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

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

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

Types in terms of McCarthy operators

Page 15: Nested Refinements: A Logic for Duck Typing

15

let getCount d c = if mem d c then toInt (d[c]) else 0

d:Dictc:StrInt

{| = true has(d,c)}

safe dictionary key lookup

get d c

Page 16: Nested Refinements: A Logic for Duck Typing

16

let incCount d c = let i = getCount d c in {d with c = i + 1}

d:Dictc:StrInt

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

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

let getCount d c = if mem d c then toInt (d[c]) else 0

set d c (i+1)

Page 17: Nested Refinements: A Logic for Duck Typing

17

T ::= {|p}

p ::= … | x :: U

U ::= y:T1T2

| A

| List T

| Null

Adding Type Constructors

“type terms”

Page 18: Nested Refinements: A Logic for Duck Typing

18

let apply f x = f x

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

{|:: A }

{|:: B }

∀A,B. (AB) A B

Page 19: Nested Refinements: A Logic for Duck Typing

19

let dispatch d f = d[f](d)

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

d :: A but additional constraints on A

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

a form of“bounded quantification”

Page 20: Nested Refinements: A Logic for Duck Typing

20

let map f xs = if xs = null then null else new List(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 21: Nested Refinements: A Logic for Duck Typing

21

let filter f xs = if xs = null then null else if not (f xs[“hd”]) then filter f xs[“tl”] else new List(xs[“hd”], filter f xs[“tl”])

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

usual definition,but an interesting type

Page 22: Nested Refinements: A Logic for Duck Typing

Outline

Intro

Examples

Subtyping

Type Soundness

Conclusion

22

Page 23: Nested Refinements: A Logic for Duck Typing

23

SMT Γ =42 tag() = “Int”

Γ {|= 42} < Int_|

(Int, IntInt)IntapplyInt ::

applyInt (42, negate)

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

Γ

type environment

Page 24: Nested Refinements: A Logic for Duck Typing

24

SMT

… negate:: x:IorB{|tag() = tag(x)}

… =negate

:: IntInt

Γ {|= negate } < {|:: IntInt }_|

(Int, IntInt)IntapplyInt ::

applyInt (42, negate)

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

Γ

type environment

Page 25: Nested Refinements: A Logic for Duck Typing

25

Γ {|= negate } < {|:: IntInt }_|

(Int, IntInt)IntapplyInt ::

applyInt (42, negate)

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

Γ

✗ distinct uninterpreted

constants!

type environment

SMT

… negate:: x:IorB{|tag() = tag(x)}

… =negate

:: IntInt

Page 26: Nested Refinements: A Logic for Duck Typing

26

IorB {|tag() = tag(x)} <: Int Int

Int <: IorB {|tag() = tag(x)} <: Int

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

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

Invalid, since these are uninterpreted constants

Want conventional syntactic subtyping

✓ ✓

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

:: Int Int✗

Page 27: Nested Refinements: A Logic for Duck Typing

27

Subtyping with Nesting

base predicate: p qij

1) Convert q to CNF clauses (q11 … ) … (qn1 … )

2) For each clause, discharge some literal qij as follows:

To prove p q :

anything except x :: Ue.g. tag() = tag(x)

e.g. tag(sel(d,k)) = “Int”

Page 28: Nested Refinements: A Logic for Duck Typing

28

Subtyping with Nesting

Implication

SMT Solver

Subtyping Arrow Rule

base predicate: p qij “has-type” predicate: p x :: U

Implication

SMT Solver

Subtyping

p x :: U’

U’ <: U

p qij

1) Convert q to CNF clauses (q11 … ) … (qn1 … )

2) For each clause, discharge some literal qij as follows:

To prove p q :

Page 29: Nested Refinements: A Logic for Duck Typing

29

UninterpretedReasoning

… negate:: x:IorB{|tag() = tag(x)}

… =negate

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

applyInt (42, negate)

Γ {|= negate } < {|:: IntInt }_|

+

SyntacticReasoning

Γ x:IorB{|tag() = tag(x)} <: IntInt_|

Page 30: Nested Refinements: A Logic for Duck Typing

Outline

Intro

Examples

Subtyping

Type Soundness

Conclusion

30

Page 31: Nested Refinements: A Logic for Duck Typing

31

0 :: {|x.x+1:: IntInt }_|

x.x+1 :: {|:: IntInt }_|

f:{|:: IntInt }0 :: {|f:: IntInt }_|

SubstitutionLemma

_| v :: TxandIf x:Tx, Γ e[:: T_|

Γ[v/x] e[v/x] :: T[v/x]_|then

independent of 0, and just echoes the binding from the environment

Page 32: Nested Refinements: A Logic for Duck Typing

32

0 :: {|x.x+1:: IntInt }_|

SMT =0 x.x+1:: IntInt✗{|=0 } < {|x.x+1:: IntInt }0 :: {|

=0 }

SubstitutionLemma

_| v :: TxandIf x:Tx, Γ e[:: T_|

Γ[v/x] e[v/x] :: T[v/x]_|then

1st attempt

Page 33: Nested Refinements: A Logic for Duck Typing

33

0 :: {|x.x+1:: IntInt }_|

{|=0 } < {|x.x+1:: IntInt }0 :: {|=0 }

SubstitutionLemma

_| v :: TxandIf x:Tx, Γ e[:: T_|

Γ[v/x] e[v/x] :: T[v/x]_|then✗SMT =0 :: U’

Arrow U’ <: IntInt

+2nd attempt✗

Page 34: Nested Refinements: A Logic for Duck Typing

34

x.x+1:: IntInt|=I

x.x+1:: {|:: IntInt }|_

SMT Γ p q

Γ {|=p } < {|=q }_|

[S-Valid-Uninterpreted]

|=I Γ p q

Γ {|=p } < {|=q }_|

[S-Valid-Interpreted]

iff

• Rule not closed under substitution

• Interpret formulas by “hooking back” into type system

• Stratification to create ordering for induction

n

n-1

n

n

Page 35: Nested Refinements: A Logic for Duck Typing

35

Type Soundness

StratifiedSubstitutionLemma

_| v :: TxandIf x:Tx, Γ e[:: T_|

Γ[v/x] e[v/x] :: T[v/x]_|then n+1

n

n

StratifiedPreservation

e vandIf e[:: T_| 0

_|then v[:: Tm for some m

“Level 0” for type checking source programs,using only [S-Valid-Uninterpreted]

artifact of the metatheory

Page 36: Nested Refinements: A Logic for Duck Typing

36

Recap• Dynamic languages make heavy use of:

– run-time tag tests, dictionary objects, lambdas

• Nested refinements– generalizes refinement type architecture– enables combination of dictionaries and lambdas

• Decidable refinement logic– all proof obligations discharged algorithmically– novel subtyping decomposition to retain precision

• Syntactic type soundness

Page 37: Nested Refinements: A Logic for Duck Typing

37

Future Work• Imperative Updates

• Inheritance (prototypes in JS, classes in Python)

• Applications

• More local type inference / syntactic sugar

• Dictionaries in statically-typed languages

Page 38: Nested Refinements: A Logic for Duck Typing

38

Thanks!

Dravichugh.com/nested

::

Page 39: Nested Refinements: A Logic for Duck Typing

39

Extra Slides

Page 40: Nested Refinements: A Logic for Duck Typing

40

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 41: Nested Refinements: A Logic for Duck Typing

41

• 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 42: Nested Refinements: A Logic for Duck Typing

42

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:{|=null Str():: ATop }

obj:{|:: A

(f=null :: AInt)

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

List[TopTop]

onto ::

functional version of Dojo function

Page 43: Nested Refinements: A Logic for Duck Typing

43

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|g=null 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 44: Nested Refinements: A Logic for Duck Typing

44

Traditional vs. Nested Refinements

Page 45: Nested Refinements: A Logic for Duck Typing

45

• Reuse refinement type architecture

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

• Define nested refinement type architecture

Approach: Refinement Types

✗✓✓*

Page 46: Nested Refinements: A Logic for Duck Typing

46

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 47: Nested Refinements: A Logic for Duck Typing

47

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 48: Nested Refinements: A Logic for Duck Typing

48

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 49: Nested Refinements: A Logic for Duck Typing

49

Subtyping (Traditional Refinements)

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

traditional refinements

Implication

SMT Solver

Subtyping

tag()=“Int” true

Int <: Top

Page 50: Nested Refinements: A Logic for Duck Typing

50

Subtyping (Traditional Refinements)

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

traditional refinements

Implication

SMT Solver

Subtyping

Top Int <: Int Int

Int <: Top Int <: Int

tag()=“Int” true

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

Page 51: Nested Refinements: A Logic for Duck Typing

51

Subtyping (Traditional Refinements)

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

traditional refinements

Implication

SMT Solver

Subtyping

Top Int <: Int Int

Int <: Top Int <: Int

tag()=“Int” true

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

Arrow Rule

Page 52: Nested Refinements: A Logic for Duck Typing

52

Subtyping (Traditional Refinements)

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

traditional refinements

Implication

SMT Solver

Subtyping Arrow Rule

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


Recommended