Type Inference with Run-time Logs

Slides:



Advertisements
Similar presentations
Types and Programming Languages Lecture 13 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Advertisements

Type Inference David Walker COS 320. Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs useful.
Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
Current Techniques in Language-based Security David Walker COS 597B With slides stolen from: Steve Zdancewic University of Pennsylvania.
1 PROPERTIES OF A TYPE ABSTRACT INTERPRETATER. 2 MOTIVATION OF THE EXPERIMENT § a well understood case l type inference in functional programming à la.
1 Mooly Sagiv and Greta Yorsh School of Computer Science Tel-Aviv University Modern Compiler Design.
1 1 Regression Verification for Multi-Threaded Programs Sagar Chaki, SEI-Pittsburgh Arie Gurfinkel, SEI-Pittsburgh Ofer Strichman, Technion-Haifa Originally.
CS7100 (Prasad)L16-7AG1 Attribute Grammars Attribute Grammar is a Framework for specifying semantics and enables Modular specification.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
INF 212 ANALYSIS OF PROG. LANGS Type Systems Instructors: Crista Lopes Copyright © Instructors.
Catriel Beeri Pls/Winter 2004/5 last 55 Two comments on let polymorphism I. What is the (time, space) complexity of type reconstruction? In practice –
Catriel Beeri Pls/Winter 2004/5 type reconstruction 1 Type Reconstruction & Parametric Polymorphism  Introduction  Unification and type reconstruction.
Type Checking in Cool Alex Aiken (Modified by Mooly Sagiv)
Type Inference with Run-time Logs Ravi Chugh. Motivation: Dynamic Languages Dynamically-typed languages – Enable rapid prototyping – Facilitate inter-language.
Type Inference David Walker COS 441. Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs useful.
CSE 130 : Winter 2006 Programming Languages Ranjit Jhala UC San Diego Lecture 7: Polymorphism.
Type Inference with Run-time Logs Ravi Chugh, Ranjit Jhala, Sorin Lerner University of California, San Diego.
CSE341: Programming Languages Lecture 11 Type Inference Dan Grossman Winter 2013.
Cs7100(Prasad)L8Proc1 Procedures. cs7100(Prasad)L8Proc2 Primitive procedures  etc User-defined procedures –Naming a sequence of operations.
CS 363 Comparative Programming Languages Semantics.
Type Inference with Run-time Logs Ravi Chugh. Motivation: Dynamic Languages Dynamically-typed languages – Enable rapid prototyping – Facilitate inter-language.
12/9/20151 Programming Languages and Compilers (CS 421) Elsa L Gunter 2112 SC, UIUC Based in part on slides by Mattox.
Just Enough Type Theory or, Featherweight Java A Simple Formal Model of Objects Jonathan Aldrich
Types and Programming Languages Lecture 11 Simon Gay Department of Computing Science University of Glasgow 2006/07.
CSE 130 : Spring 2011 Programming Languages Ranjit Jhala UC San Diego Lecture 5: Functions and Closures.
COMP 412, FALL Type Systems II C OMP 412 Rice University Houston, Texas Fall 2000 Copyright 2000, Robert Cartwright, all rights reserved. Students.
Types and Programming Languages Lecture 14 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Shifting the Blame A blame calculus with delimited control Taro Sekiyama* Atsushi Igarashi Soichiro Ueda Kyoto University Gradual typing.
LECTURE 3 Compiler Phases. COMPILER PHASES Compilation of a program proceeds through a fixed series of phases.  Each phase uses an (intermediate) form.
Type Inference with Run-time Logs Ravi Chugh, Ranjit Jhala, Sorin Lerner University of California, San Diego.
The Ins and Outs of Gradual Type Inference Avik Chaudhuri Basil Hosmer Adobe Systems Aseem Rastogi Stony Brook University.
COMP 412, FALL Type Systems C OMP 412 Rice University Houston, Texas Fall 2000 Copyright 2000, Robert Cartwright, all rights reserved. Students.
Arvind Computer Science and Artificial Intelligence Laboratory M.I.T. L05-1 September 21, 2006http:// Types and Simple Type.
LECTURE 10 Semantic Analysis. REVIEW So far, we’ve covered the following: Compilation methods: compilation vs. interpretation. The overall compilation.
Heath Carroll Bill Hanczaryk Rich Porter.  A Theory of Type Polymorphism in Programming ◦ Robin Milner (1977)  Milner credited with introducing the.
Lesson 10 Type Reconstruction
Functional Programming
Type Checking and Type Inference
Programming Languages and Compilers (CS 421)
CSE341: Programming Languages Lecture 11 Type Inference
Functions.
Semantic Analysis Type Checking
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists
Type Systems Terms to learn about types: Related concepts: Type
Semantic Analysis Chapter 6.
Data Types.
Programming Languages and Compilers (CS 421)
Recursion "To understand recursion, one must first understand recursion." -Stephen Hawking.
Compiler Design 18. Object Oriented Semantic Analysis (Symbol Tables, Type Checking) Kanat Bolazar March 30, 2010.
Names, Binding, and Scope
Lecture 23 Pages : Separating Syntactic Analysis from Execution. We omit many details so you have to read the section in the book. The halting.
FP Foundations, Scheme In Text: Chapter 14.
CSE341: Programming Languages Lecture 11 Type Inference
Dynamic Scoping Lazy Evaluation
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists
CSE341: Programming Languages Lecture 11 Type Inference
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists
6.001 SICP Further Variations on a Scheme
Language-based Security
Haskell Types, Classes, and Functions, Currying, and Polymorphism
L Calculus.
CSE341: Programming Languages Lecture 11 Type Inference
Type Systems Terms to learn about types: Related concepts: Type
Program correctness Axiomatic semantics
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists
CSE341: Programming Languages Lecture 11 Type Inference
CSE341: Programming Languages Lecture 2 Functions, Pairs, Lists
CSE341: Programming Languages Lecture 11 Type Inference
Presentation transcript:

Type Inference with Run-time Logs Ravi Chugh, Ranjit Jhala, Sorin Lerner University of California, San Diego

Motivation: Dynamic Languages Dynamically-typed languages Enable rapid prototyping Facilitate inter-language development Statically-typed languages Prevent certain run-time errors Enable optimized execution Provide checked documentation Many research efforts to combine both Recent popularity of Python, Ruby, and JavaScript has stoked the fire

Gradual Type Systems Many attempts at fully static type systems Often require refactoring and annotation Some features just cannot be statically typed Gradual type systems provide a spectrum Some expressions have types, statically-checked Others are dynamic, fall back on run-time checks Challenges Granularity, guarantees, blame tracking, and ...

... Inference! Goal: migrate programs from dynamic langs Programmer annotation burden is currently 0 A migration strategy must require ~0 work Even modifying 1-10% LOC in a large codebase can be prohibitive

The Challenge: Inference Goal: practical type system polymorphism def id(x) { return x }; 1 + id(2); “hello” ^ id(“world”); id : ∀X. X → X polymorphism

The Challenge: Inference Goal: practical type system subtyping def succA(x) { return (1 + x.a) }; succA({a=1}); succA({a=1;b=“hi”}); {a:Int;b:Str} <: {a:Int} subtyping polymorphism

The Challenge: Inference Goal: practical type system bounded quantification def incA(x) { x.a := 1 + x.a; return x }; incA({a=1}).a; incA({a=1;b=“hi”}).b; bounded quantification subtyping incA : ∀X<:{a:Int}. X → X polymorphism

The Challenge: Inference Goal: practical type system dynamic n := if b then 0 else “bad”; m := if b then n + 1 else 0; dynamic bounded quantification n : dynamic subtyping polymorphism

The Challenge: Inference Goal: practical type system other features... dynamic bounded quantification subtyping polymorphism

The Challenge: Inference Goal: practical type system other features... dynamic bounded quantification subtyping polymorphism System ML ✓

The Challenge: Inference Goal: practical type system other features... dynamic bounded quantification subtyping System F ✗ polymorphism

The Idea Use run-time executions to help inference Program may have many valid types But particular execution might rule out some Dynamic language programmers test a lot Use existing test suites to help migration

Route: Inference w/ Run-time Logs omit higher-order functions System E≤ bounded quantification System E subtyping + polymorphism

omit higher-order functions First Stop omit higher-order functions System E≤ bounded quantification System E subtyping + polymorphism System E−

E− Type System Expression and function types τ ::= | Int | Bool | ... | {fi:τi} | X σ ::= ∀Xi. τ1 → τ2 Typing rules prevent field-not-found and primitive operation errors

def id (a) { a } def id[A] (a:A) { a } : ∀A. A → A def id[] (a:Int) { a } : Int → Int def id[B,C] (x:B*C) { a } : ∀B,C. B*C → B*C Infinitely many valid types for id...

... but ∀A. A → A is the principal type Int → Int ∀B,C. B*C → B*C

... but ∀A. A → A is the principal type More general than every other type Allows id to be used in most different ways ∀A. A → A Int → Int ∀B,C. B*C → B*C ∀B. B*B → B*B Int*Bool → Int*Bool Int*Int → Int*Int

def readF[F] (o:{f:F}) { o.f } : ∀F. {f:F} → F This is the best type def readF (o) { o.f } def readF[F] (o:{f:F}) { o.f } : ∀F. {f:F} → F This is the best type ∀F. {f:F} → F {f:Int} → Int ∀F,G. {f:F;g:G} → F ∀G. {f:Int;g:G} → Int

∀F,G. {f:F;g:G} → {f:F;g:G} def hasF (x) { let _ = x.f in x } Two valid types: Neither is better than the other ∀F. {f:F} → {f:F} ∀F,G. {f:F;g:G} → {f:F;g:G} allows hasF({f=1}) allows hasF({f=1;g=2}).g

E− Static Type Inference E− lacks principal types Cannot assign type just from definition Need to consider calling contexts Our approach is iterative Impose minimal constraints on argument If a calling context requires an additional field to be tracked, backtrack and redo the function

Iterative Inference – Example 1 def hasF(x) { let _ = x.f in x } def main1() { hasF({f=1}) } ✓ Constraints on x Solution X = {f:F}x X <: {f:F} “this record type came from the program variable x” hasF : ∀F. {f:F} → {f:F}x 22

Iterative Inference – Example 2 ✗* def hasF(x) { let _ = x.f in x } def main2() { let z = {f=1;g=2} in hasF(z).g } hasF(z) : {f:Int}x so can’t project on g, unless... Constraints on x Solution X = {f:F}x X <: {f:F} X <: {g:G} hasF : ∀F. {f:F} → {f:F}x 23

Iterative Inference – Example 2 def hasF(x) { let _ = x.f in x } def main2() { let z = {f=1;g=2} in hasF(z).g } ✓ Constraints on x Solution X = {f:F;g:G}x X <: {f:F} X <: {g:G} hasF : ∀F,G. {f:F;g:G} → {f:F;g:G}x 24

Iterative Inference – Example 3 def hasF(x) { let _ = x.f in x } def main3() { let z = {f=1;g=2} in hasF(z).g; hasF({f=1}) } Constraints on x Solution X = {f:F;g:G}x X <: {f:F} X <: {g:G} hasF : ∀F,G. {f:F;g:G} → {f:F;g:G}x 25

Iterative Inference – Example 3 def hasF(x) { let _ = x.f in x } def main3() { let z = {f=1;g=2} in hasF(z).g; hasF({f=1}) } ✓ ✗ Constraints on x Solution X = {f:F;g:G}x X <: {f:F} X <: {g:G} hasF : ∀F,G. {f:F;g:G} → {f:F;g:G}x 26

E− Type Inference with Run-time Logs Evaluation can log caller-induced constraints Wrap all values with sets of type variables When a value passed to arg x, add Xx tag When a value with tag Xx.l projected on field f, record Xx.l <: {f : Xx.l.f} Iteration 0 of modified inference looks in log for caller-induced constraints 27

Caller-induced constraint def hasF(x) { let _ = x.f in x } def main2() { let z = {f=1;g=2} in hasF(z).g } Evaluation main2() ⇒ let z = {f=1;g=2} in hasF(z).g ⇒ let z = [{f=1;g=2},{}] in hasF(z).g ⇒ hasF([{f=1;g=2},{Xx}]).g ⇒ (let _ = [{f=1;g=2},{Xx}].f in [{f=1;g=2},{Xx}]).g ⇒ (let _ = [1,{Xx.f}] in [{f=1;g=2},{Xx}]).g ⇒ [{f=1;g=2},{Xx}].g ⇒ [2,{Xx.g}] Run-time log Xx <: {f : Xx.f} Caller-induced constraint Xx <: {g : Xx.g} 28

System E− Summary Fully static inference needs to iterate, but can optimize with run-time information Can wrap run-time values with sets of type variables and record field read constraints If all expressions executed, then log contains all caller-induced constraints no need for iteration

Next Stop System E≤ System E System E System E− bounded quantification subtyping + polymorphism System E−

If-expressions Type is a supertype of branch types if b then 1 else 2 : Int if b then 1 else true : Top if b then {f=1; g=“”} else {f=2; h=true} : {f:Int} if b then {f=“”} else {f=true} : {f:Top}

Four valid incomparable types: def choose (y,z) { if1 y.n > 0 then y else z } Four valid incomparable types: ∀A. {n:Int}*{} → {} ∀A. {n:Int}*{n:Top} → {n:Top} {n:Int}*{n:Int} → {n:Int} ∀B. {n:Int;b:B}*{n:Int;b:B} → {n:Int;b:B}

Iterative Inference – Example def choose(y,z) { if1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } Constraints Y <: {n:N} N = Int choose : {n:Int}*{} → {}1 Iteration 0 “this record type came from the if-expression 1” 33 33

t : {}1 so can’t project on n Iterative Inference – Example def choose(y,z) { if1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } ✗* t : {}1 so can’t project on n Constraints Y <: {n:N} N = Int Z <: {n:M} choose : {n:Int}*{} → {}1 Iteration 0 choose : {n:Int}*{n:Top1.n} → {n:Top1.n}1 Iteration 1 34 34

✗* Iterative Inference – Example def choose(y,z) { if1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } ✗* t.n : Top1.n so can’t add Constraints Y <: {n:N} N = Int Z <: {n:M} N = M choose : {n:Int}*{} → {}1 Iteration 0 choose : {n:Int}*{n:Top1.n} → {n:Top1.n}1 Iteration 1 choose : {n:Int}*{n:Int} → {n:Int}1 Iteration 2 35 35

✓ Iterative Inference – Example def choose(y,z) { if1 y.n > 0 then y else z } def main4() { let t = choose({n=1},{n=2}) in succ t.n } ✓ Constraints Y <: {n:N} N = Int Z <: {n:M} N = M choose : {n:Int}*{} → {}1 Iteration 0 choose : {n:Int}*{n:Top1.n} → {n:Top1.n}1 Iteration 1 choose : {n:Int}*{n:Int} → {n:Int}1 Iteration 2 36 36

System E Summary Lacks principal types Has iterative inference Use subscripts for record types from if-exps Run-time info removes iteration, as before

Last Stop System E≤ System E≤ System E System E− bounded quantification System E subtyping + polymorphism System E−

∀F,G. {f:F;g:G} → {f:F;g:G} def hasF (x) { let _ = x.f in x } Now there is a best type for hasF Each call site can instantiate X differently ∀F, X<:{f:F}. X → X ∀F. {f:F} → {f:F} ∀F,G. {f:F;g:G} → {f:F;g:G} 39

{n:Int}*{n:Int} → {n:Int} def choose (y,z) { if1 y.n > 0 then y else z } {n:Int}*{n:Int} → {n:Int} ∀B. {n:Int;b:B}*{n:Int;b:B} → {n:Int;b:B} {n:Int}*{} → {} ∀Y<:{n:Int}. Y * Y → Y

choose({n=1,b=true}, {n=2,b=false}).b def choose (y,z) { if1 y.n > 0 then y else z } {n:Int}*{} → {} ∀Y<:{n:Int}. Y * Y → Y allows choose({n=1},{}) allows choose({n=1},{n=2}).n and choose({n=1,b=true}, {n=2,b=false}).b Neither type is better

Sharing Bounded Type Variables E≤ lacks principal types Can type variables for y and z be shared? If their separate bounds are compatible Y<:{n:Int} and Z<:{} can be combined to {n:Int} Y<:{n:Int} and Z<:{n:Bool} cannot be combined 42

E≤ Inference For all program variables returned by an if: If bounds not compatible, use separate variables Otherwise, use same type variable All call sites well-typed Otherwise, restart and keep vars separate Using separate variables is just like System E Now there is a second cause for restarting 43

E≤ Inference with Run-time Logs Know when to share from run-time info? Can’t determine if all call sites well-typed even if actual has a field, its static type might not Can determine if some call site is not if an actual doesn’t have field, static type will not So can eliminate some iteration but not all 44

System E≤ Summary Lacks principal types Primary new challenge: determining when to use same type variable for y and z Static inference has new source of iteration Cannot be eliminated with run-time info

Summary System E≤ System E System E− bounded quantification subtyping + polymorphism System E−

Summary Iterative static inference for E≤ first-order functions, records polymorphism, subtyping bounded quantification Run-time information improves algorithms reduces worst-case complexity (not counting overhead for instrumented eval)

Future Work Direction #0: Prove formal properties for E≤ Direction #1: Extend E≤ recursion, recursive types, dynamic, classes, ... is there still static inference? how can run-time info help? can existing programs be encoded in E? Direction #2: Inference for F does inference become easier with run-time info? if so, extend with more features if not, heuristic-based approaches for migration

Goseichou arigatou gozaimashita! Original photo by Alaskan Dude Released under Creative Commons Attribution 2.0 Generic License

Extra Slides

Typed vs. Untyped Syntax Function definitions Function calls Program is sequence of function definitions def y[A1,...,An](x:τ){ e } def y(x){ e’ } y[τ1,...,τn](e) y(e’)

Bounded Quantification def y[ A1<:τ1 , ... , An<:τn ] (x:τ) { e } Type parameters now have bounds

∀Y,Z. (Y<:{n:Int}, Y<:Z) => Y*Z → Z Bounded Quantification With arbitrary subtyping constraints, choose has a principal type ∀Y,Z. (Y<:{n:Int}, Y<:Z) => Y*Z → Z 53

Related Work Complete inference for ML + records [Remy 89] limited by ML polymorphism and fields cannot be forgotten Type inference for F is undecidable [Wells 94] Local type inference for F [Pierce et al, Odersky et al, et al] require top-level annotations, try to fill in rest even partial inference for F undecidable [Pfenning 88] Type checking for F≤ is undecidable [Pierce 91]

Related Work Static type systems for dynamic languages type systems for JavaScript [Thiemann 05, et al] Typed Scheme [Tobin-Hochstadt and Felleisen 08] Diamondback Ruby [Furr et al 09 11] Gradual type systems functions [Thatte 90, Cartwright and Fagan 91, Siek and Taha 06] objects [Siek and Taha 07, Wrigstad et al 10, Bierman et al 10] Coercion insertion [Henglein/Rehof 95, Siek/Vachharajani 08] do not deal with records