Nested Refinements: A Logic for Duck Typing :: Ravi Chugh, Pat - - PowerPoint PPT Presentation

nested refinements
SMART_READER_LITE
LIVE PREVIEW

Nested Refinements: A Logic for Duck Typing :: Ravi Chugh, Pat - - PowerPoint PPT Presentation

Nested Refinements: A Logic for Duck Typing :: Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD) WhatareDynamicLanguages? affectcontrolflow tagtests indexedbyarbitrarystringkeys dic<onaryobjects


slide-1
SLIDE 1

Nested Refinements: A Logic for Duck Typing

Ravi Chugh, Pat Rondon, Ranjit Jhala (UCSD)

::

slide-2
SLIDE 2

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
 dic<onary
objects 
 indexed
by
arbitrary
string
keys
 first‐class
func<ons 
 can
appear
inside
objects


slide-3
SLIDE 3

3 


Problem:
Lack
of
sta<c
types



 …
makes
rapid
prototyping
/
mul<‐language
applica<ons
easy
 
 …
makes
reliability
/
performance
/
maintenance
hard


This
Talk:
System
D



 …
a
type
system
for
these
features


tag
tests 
 affect
control
flow
 dic<onary
objects 
 indexed
by
arbitrary
string
keys
 first‐class
func<ons 
 can
appear
inside
objects


slide-4
SLIDE 4

… 


  • ccurrence


types 
 ∨,
∧ 


Our
Approach:
Quan<fier‐free
formulas


tag
tests 
 affect
control
flow
 dic<onary
objects 
 indexed
by
arbitrary
string
keys
 first‐class
func<ons 
 can
appear
inside
objects
 Expressiveness 
 Usability 
 F≤

Coq 
 refinement
 types 
 nested
 refinements 
 syntac<c
approaches 
 dependent
approaches 



1.
increase
expressiveness
 
2.
retain
level
of
automa<on


slide-5
SLIDE 5

5 


Func<ons
inside
dic<onaries
 Challenge:


{ ν | tag(ν) = “Int” ∨ tag(ν) = “Bool” } x :: { ν | tag(ν) = “Dict” ∧ tag(sel(ν,“n”)) = “Int” ∧ tag(sel(ν,m)) = “Int” } d :: tag
tests 
 affect
control
flow
 dic<onary
objects 
 indexed
by
arbitrary
string
keys
 first‐class
func<ons 
 can
appear
inside
objects


slide-6
SLIDE 6

6 


Key
Idea:
Nested
Refinements


{ ν | tag(ν) = “Dict” ∧ sel(ν,f) :: } d :: →

{ ν | tag(ν)=“Int” } { ν | tag(ν)=“Int” }

uninterpreted
predicate
 “x :: U”
says
 “x
has‐type
U”
 syntac<c
arrow
type…
 1 + d[f](0)

slide-7
SLIDE 7

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) syntac<c
arrow
type…
 …
but
uninterpreted
 constant
in
the
logic


slide-8
SLIDE 8
  • All
values
described
by
refinement
formulas


T ::= { ν | p }


  • “Has‐type”
predicate
for
arrows
in
formulas


p ::= … | x :: y:T1 → T2


  • Can
express
idioms
of
dynamic
languages

  • Automa<c
type
checking


– Decidable
refinement
logic
 – Subtyping
=
SMT
Validity
+
Syntac<c
Subtyping


8 


Key
Idea:
Nested
Refinements


slide-9
SLIDE 9

Outline


Intro
 Examples
 Subtyping
 Type
Soundness
 Conclusion


9 


slide-10
SLIDE 10

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 }

slide-11
SLIDE 11

IntOrBool x :: Γ

11 


{ ν | 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 


✓


slide-12
SLIDE 12

IntOrBool x :: Γ

12 


{ ν | 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 


✓
 ✓
 ✓


slide-13
SLIDE 13

13 


{ ν | ν :: } x: →

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

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

Nes<ng
structure
hidden
with
syntac<c
sugar


slide-14
SLIDE 14

Dic<onary
Opera<ons


14 


d:Dict → k:Str → { ν | ν = true ⇔ has(d,k) } mem :: d:Dict → k:{ ν | has(d,ν) } → { ν | ν = sel(d,k) } get :: d:Dict → k:Str → x:Top → { ν | ν = upd(d,k,x) } set ::

Types
in
terms
of
McCarthy
operators


slide-15
SLIDE 15

15 


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

d:Dict → c:Str → Int { ν | ν = true ⇔ has(d,c) }

safe
dic<onary
 key
lookup


get d c

slide-16
SLIDE 16

16 


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

d:Dict → c:Str → Int d:Dict → c: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)

slide-17
SLIDE 17

T ::= { ν | p }
 p ::= … | x :: U U ::= y:T1 → T2 | A | List T | Null

17 


Adding
Type
Constructors


“type
terms”


slide-18
SLIDE 18

18 


let apply f x = f x

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

slide-19
SLIDE 19

19 


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

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

d :: A
but
addi<onal
constraints
on
A ≈ ∀A <: {f: A → B}. d :: A a
form
of
 “bounded
quan<fica<on”

slide-20
SLIDE 20

20 


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

∀A,B. { ν | ν :: A → B } → { ν | ν :: List[A] } → { ν | ν :: List[B] }

encode
recursive
data
as
dic<onaries


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

slide-21
SLIDE 21

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 → { ν | ν = true ⇒ x :: B } → List[A] → List[B]

usual
defini<on,
 but
an
interes<ng
type


slide-22
SLIDE 22

Outline


Intro
 Examples
 Subtyping
 Type
Soundness
 Conclusion


22 


slide-23
SLIDE 23

23 


SMT


Γ ∧ ν = 42 ⇒ tag(ν) = “Int” Γ { ν | ν = 42 } < Int _ | (Int, Int → Int) → Int applyInt :: applyInt (42, negate) x:IntOrBool → { ν | tag(ν) = tag(x) } negate :: Γ

✓


type
environment


slide-24
SLIDE 24

SMT


… ∧ negate :: x:IorB → { ν | tag(ν) = tag(x) } … ∧ ν = negate
 ⇒ ν :: Int → Int

24 


Γ { ν | ν = negate } < { ν | ν :: Int → Int } _ | (Int, Int → Int) → Int applyInt :: applyInt (42, negate) x:IntOrBool → { ν | tag(ν) = tag(x) } negate :: Γ type
environment


slide-25
SLIDE 25

25 


Γ { ν | ν = negate } < { ν | ν :: Int → Int } _ | (Int, Int → Int) → Int applyInt :: applyInt (42, negate) x:IntOrBool → { ν | tag(ν) = tag(x) } negate :: Γ

✗


dis<nct
 uninterpreted
 constants!


type
environment


SMT


… ∧ negate :: x:IorB → { ν | tag(ν) = tag(x) } … ∧ ν = negate
 ⇒ ν :: Int → Int

slide-26
SLIDE 26

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
conven<onal
syntac<c
subtyping


✓
 ✓


ν :: x:IorB → { ν | tag(ν) = tag(x) } ⇒ ν :: Int → Int

✗


slide-27
SLIDE 27

Subtyping
with
Nes<ng


27 


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 :: U e.g.
tag(ν) = tag(x) e.g.
tag(sel(d,k)) = “Int”

slide-28
SLIDE 28

Subtyping
with
Nes<ng


28 


Implica<on
 SMT
Solver
 Subtyping
 Arrow
Rule
 base
predicate: p
⇒
qij “has‐type”
predicate: p
⇒
x :: U Implica<on
 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
:

slide-29
SLIDE 29

Uninterpreted
 Reasoning
 … ∧ negate :: x:IorB → { ν | tag(ν) = tag(x) } … ∧ ν = negate
 ⇒ ν :: x:IorB → { ν | tag(ν) = tag(x) }

29 


applyInt (42, negate) Γ { ν | ν = negate } < { ν | ν :: Int → Int } _ |

+

Syntac<c
 Reasoning
 Γ x:IorB → { ν | tag(ν) = tag(x) } <: Int → Int _ |

slide-30
SLIDE 30

Outline


Intro
 Examples
 Subtyping
 Type
Soundness
 Conclusion


30 


slide-31
SLIDE 31

31 


0 :: { ν | λx.x+1 :: Int → Int } _ | λx.x+1 :: { ν | ν :: Int → Int } _ | f:{ ν | ν :: Int → Int } 0 :: { ν | f :: Int → Int } _ |

Subs<tu<on
 Lemma


_ | v :: Tx and
 If
 x:Tx, Γ e[:: T _ | Γ[v/x] e[v/x] :: T[v/x] _ | then


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


slide-32
SLIDE 32

32 


0 :: { ν | λx.x+1 :: Int → Int } _ |

SMT


ν = 0 ⇒ λx.x+1 :: Int → Int

✗


{ ν | ν = 0 } < { ν | λx.x+1 :: Int → Int } 0 :: { ν | ν = 0 }

Subs<tu<on
 Lemma


_ | v :: Tx and
 If
 x:Tx, Γ e[:: T _ | Γ[v/x] e[v/x] :: T[v/x] _ | then


1st
alempt


slide-33
SLIDE 33

33 


0 :: { ν | λx.x+1 :: Int → Int } _ | { ν | ν = 0 } < { ν | λx.x+1 :: Int → Int } 0 :: { ν | ν = 0 }

Subs<tu<on
 Lemma


_ | v :: Tx and
 If
 x:Tx, Γ e[:: T _ | Γ[v/x] e[v/x] :: T[v/x] _ | then


✗


SMT


ν = 0 ⇒ ν :: U’ Arrow
 U’ <: Int → Int

+

2nd
alempt


✗


slide-34
SLIDE 34

34 


λx.x+1 :: Int → Int

| = I

λx.x+1 :: { ν | ν :: Int → Int }

| _

SMT
 Γ ∧ p ⇒ q

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

[S‐Valid‐Uninterpreted]


| = I Γ ∧ p ⇒ q

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

[S‐Valid‐Interpreted]


iff


  • Rule
not
closed
under


subs<tu<on


  • Interpret
formulas
by


“hooking
back”
into
 type
system


  • Stra<fica<on
to
create

  • rdering
for
induc<on


n n-1

n

n

slide-35
SLIDE 35

Type
Soundness


35 


Stra<fied
 Subs<tu<on
 Lemma


_ | v :: Tx and
 If
 x:Tx, Γ e[:: T _ | Γ[v/x] e[v/x] :: T[v/x] _ | then


n+1 n n

Stra<fied
 Preserva<on


e  v and
 If
 e[:: T _ | 0 _ | then
 v[:: T

m

for
some
m


“Level
0”
for
type
checking
source
programs,
 using
only
[S‐Valid‐Uninterpreted]
 ar<fact
of
the
metatheory


slide-36
SLIDE 36

Recap


  • Dynamic
languages
make
heavy
use
of:


– run‐<me
tag
tests,
dic<onary
objects,
lambdas


  • Nested
refinements


– generalizes
refinement
type
architecture
 – enables
combina<on
of
dic<onaries
and
lambdas


  • Decidable
refinement
logic


– all
proof
obliga<ons
discharged
algorithmically
 – novel
subtyping
decomposi<on
to
retain
precision


  • Syntac<c
type
soundness


36 


slide-37
SLIDE 37

Future
Work


  • Impera<ve
Updates

  • Inheritance
(prototypes
in
JS,
classes
in
Python)

  • Applica<ons

  • More
local
type
inference
/
syntac<c
sugar

  • Dic<onaries
in
sta<cally‐typed
languages


37 


slide-38
SLIDE 38

38 


Thanks!


D

ravichugh.com/nested

::

slide-39
SLIDE 39

39 


Extra
Slides


slide-40
SLIDE 40

Constants


40 


tagof :: x:Top → { ν | ν = tag(x) } mem :: d:Dict → k:Str → { ν | Bool(ν) ∧ ν = True ⇔
has(d,k) } get :: d:Dict → k:{ ν | Str(ν) ∧ has(d,ν) } → { ν | ν = sel(d,k) } set :: d:Dict → k:Str → x:Top → { ν | ν = upd(d,k,x) } rem :: d:Dict → k:Str → { ν | ν = upd(d,k,bot) }

slide-41
SLIDE 41
  • Types

  • Formulas

  • Logical
Values


Macros


41 


{ ν | tag(ν)=“Int” } Int ≡ x:T1 → T2 ≡ { ν | ν :: } x:T1 → T2 tag(x) = “Str” Str(x) ≡ sel(ν,“k”) x.k ≡ sel(ν,k) x[k] ≡ sel(d,k) != bot has(d,k) ≡ ∀k’. k’ != k ⇒
 sel(d,k) != sel(d’,k) EqMod(d,d’,k) ≡

slide-42
SLIDE 42

Onto


42 


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) ∀A. callbacks:List[Top → Top] → f:{ ν | ν = null ∨ Str(ν) ∨ ν :: A → Top } → obj:{ ν | ν :: A ∧ (f = null ⇒ ν :: A → Int) ∧ (Str(f) ⇒ ν[f] :: A → Int) } → List[Top → Top]

  • nto ::

func<onal
version
of
Dojo
func<on 


slide-43
SLIDE 43

Onto
(2)


43 


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[Top → Top] * 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[Top → Top]

  • nto ::

func<onal
version
of
Dojo
func<on 


slide-44
SLIDE 44

44 


Tradi<onal
vs.
Nested
Refinements


slide-45
SLIDE 45

45 


  • Reuse
refinement
type
architecture

  • Find
a
decidable
refinement
logic
for


– Tag‐tests
 – Dic<onaries
 – Lambdas


  • Define
nested
refinement
type
architecture


Approach:
Refinement
Types


✓
 ✗
 ✓
 ✓*


slide-46
SLIDE 46

46 


Nested
Refinements


T ::= { ν | p }
 U ::= x:T1 → T2
 p ::= p ∧ q | …
 | x = y | x < y | … | tag(x) = “Int” | …
 | sel(x,y) = z | …
 | x :: U

  • Refinement
formulas
over
a
decidable
logic


– uninterpreted
func<ons,
McCarthy
arrays,
linear
arithme<c


  • Only
base
values
refined
by
formulas


All
values


T ::= { ν | p }
 | x:T1 → T2
 p ::= p ∧ q | …
 | x = y | x < y | … | tag(x) = “Int” | …
 | sel(x,y) = z | … tradi<onal
refinements

slide-47
SLIDE 47

47 


Nested
Refinements


T ::= { ν | p }
 U ::= x:T1 → T2
 p ::= p ∧ q | …
 | x = y | x < y | … | tag(x) = “Int” | …
 | sel(x,y) = z | …
 | x :: U

  • Refinement
formulas
over
a
decidable
logic


– uninterpreted
func<ons,
McCarthy
arrays,
linear
arithme<c


  • Only
base
values
refined
by
formulas

  • “has‐type”
allows
“type
terms”
in
formulas


All
values


T ::= { ν | p }
 | x:T1 → T2
 p ::= p ∧ q | …
 | x = y | x < y | … | tag(x) = “Int” | …
 | sel(x,y) = z | … tradi<onal
refinements

slide-48
SLIDE 48

48 


Nested
Refinements


T ::= { ν | p }
 U ::= x:T1 → T2
 p ::= p ∧ q | …
 | x = y | x < y | … | tag(x) = “Int” | …
 | sel(x,y) = z | …
 | x :: U

  • Refinement
formulas
over
a
decidable
logic


– uninterpreted
func<ons,
McCarthy
arrays,
linear
arithme<c


  • Only
base
values
refined
by
formulas

  • “has‐type”
allows
“type
terms”
in
formulas


All
values


slide-49
SLIDE 49

Subtyping
(Tradi<onal
Refinements)


49 


T ::= { ν | p }
 | x:T1 → T2
 tradi<onal
refinements

Implica<on
 SMT
Solver
 Subtyping
 tag(ν)=“Int” ⇒ true Int <: Top

slide-50
SLIDE 50

Subtyping
(Tradi<onal
Refinements)


50 


T ::= { ν | p }
 | x:T1 → T2
 tradi<onal
refinements

Implica<on
 SMT
Solver
 Subtyping
 Top → Int <: Int → Int Int <: Top Int <: Int

tag(ν)=“Int” ⇒ true tag(ν)=“Int” ⇒ tag(ν)=“Int”

slide-51
SLIDE 51

Subtyping
(Tradi<onal
Refinements)


51 


T ::= { ν | p }
 | x:T1 → T2
 tradi<onal
refinements

Implica<on
 SMT
Solver
 Subtyping
 Top → Int <: Int → Int Int <: Top Int <: Int

tag(ν)=“Int” ⇒ true tag(ν)=“Int” ⇒ tag(ν)=“Int”

Arrow
Rule


slide-52
SLIDE 52

Subtyping
(Tradi<onal
Refinements)


52 


T ::= { ν | p }
 | x:T1 → T2
 tradi<onal
refinements

Implica<on
 SMT
Solver
 Subtyping
 Arrow
Rule


Decidable
if:


  • Only
values
in
formulas

  • Underlying
theories
decidable