A Bidirectional Krivine...
Transcript of A Bidirectional Krivine...
Mikaël Mayer Ravi Chugh
A Bidirectional Krivine Evaluator
Bx 2019
A Bidirectional Krivine Evaluator
Bx 2019
2
Bidirectional Evaluation
OOPSLA 2018
A Bidirectional Krivine Evaluator
Bx 2019
3
4
( Edit Program; Run; View Output )+
5
( Edit Program; Run; View Output )+
6
( Edit Program; Run; View Output )+
7
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
( Edit Program; Run; View Output )+
8
( Edit Program; Run; View Output; Edit Output )+
Synthesize Program Repair
Our Goal
9
let f x = x ++ " 2018" in
10
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW"
11
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW"
"B 2018 @ PLW 2018" ⇒
12
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW"
"B 2018 @ PLW 2018" ⇒ ⇝"Bx 2019 @ PLW 2018"
13
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW"
"B 2018 @ PLW 2018" ⇒ ⇝"Bx 2019 @ PLW 2018" ⇐ let f x = x ++ " 2019" in
f "Bx" ++ " @ " ++ f "PLW"
14
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW"
"B 2018 @ PLW 2018" ⇒ ⇝"Bx 2019 @ PLW 2018" ⇐let f x = x ++ " 2019" in
f "Bx" ++ " @ " ++ f "PLW"
15
"Bx 2019 @ PLW 2019"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW" ⇒
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW"
"B 2018 @ PLW 2018" ⇒ ⇝"Bx 2019 @ PLW 2018" ⇐let f x = x ++ " 2019" in
f "Bx" ++ " @ " ++ f "PLW"
16
"B 2018 @ PLW 2018"
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW" ⇒ ⇝
⇐ "Bx 2019 @ PLW 2018"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW"
"Bx 2019 @ PLW 2019"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW" ⇒
17
"B 2018 @ PLW 2018"
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW" ⇒ ⇝
⇐ "Bx 2019 @ PLW 2018"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW"
"Bx 2019 @ PLW 2019"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW" ⇒
Unrestricted function
18
"B 2018 @ PLW 2018"
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW" ⇒ ⇝
⇐ "Bx 2019 @ PLW 2018"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW"
"Bx 2019 @ PLW 2019"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW" ⇒
Unrestricted function
Repair "code" + "data"
19
"B 2018 @ PLW 2018"
let f x = x ++ " 2018" in f "B" ++ " @ " ++ f "PLW" ⇒ ⇝
⇐ "Bx 2019 @ PLW 2018"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW"
"Bx 2019 @ PLW 2019"
let f x = x ++ " 2019" in f "Bx" ++ " @ " ++ f "PLW" ⇒
Unrestricted function
Repair "code" + "data"
Extra repairs
20
'' ⇒ ⇝
⇐
⇒
Unrestricted function
Repair "code" + "data"
Extra repairs
21
⇒ ⇝
⇐
⇒
Unrestricted function
Repair "code" + "data"
Extra repairs
y'' L' x' L.get
22
⇒ ⇝
⇐
⇒
Unrestricted function
Repair "code" + "data"
Extra repairs
y'' L' x' L.get
y'' L' x' L.put
23
y'' L' x' ⇒ ⇝
⇐ y'' L' x'
y'' L' x' ⇒
Unrestricted function
Repair "code" + "data"
Extra repairs
L.get
L.get
L.put
24
y'' f' x' ⇒ ⇝
⇐ y'' f'' x'
y'' f'' x' ⇒
Unrestricted function
Repair "code" + "data"
Extra repairs
25
v'' e' ⇒ ⇝
⇐ v'' e'
v'' e' ⇒
26
v'' e' ⇒ ⇝
⇐ v'' e'
v'' e' ⇒
Every exp (code + data)…���
… runs backward and updated
27
v'' e' ⇒ ⇝
⇐ v'' e'
v'' e' ⇒
Every exp (code + data)…���
… runs backward and updated
Don't (necessarily) enforce PutGet law
28
e') ⇒'v'
e') ⇐ 'v'
⇝Bidirectional Evaluation
29
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐ 'v'
⇝Bidirectional Evaluation
Environment-style semantics���simplifies the system
30
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐ 'v'
⇝
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
31
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
32
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
33
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
(– ⊢ 2018) ⇒'2018
2019
⇝
34
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
(– ⊢ 2018) ⇒'2018
(– ⊢ 2019) ⇐' 2019
⇝
35
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
36
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
(– ⊢ let x = 2018 in x) ⇒'2018
2019
⇝
37
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ 2018) ⊢ x) ⇒'2018
2019
⇝
38
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ 2018) ⊢ x) ⇒'2018
((x ↦ 2019) ⊢ x) ⇐' 2019
⇝
39
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
(– ⊢ let x = 2018 in x) ⇒'2018
(– ⊢ let x = 2019 in x) ⇐ '2019
⇝
40
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
41
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
(– ⊢ let x = 18 in (x, x)) ⇒'(18, 18)
(19, 18)
⇝
42
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ 18 ) ⊢ (x, x)) ⇒'(18, 18)
(19, 18)
⇝
43
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ 18 ) ⊢ (x, x)) ⇒'(18, 18)
((x ↦ 19 ) ⊢ (x, x)) ⇐' (19, 18)
⇝ 18?���
19?
44
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ 18 ) ⊢ (x, x)) ⇒'(18, 18)
((x ↦ 19 ) ⊢ (x, x)) ⇐' (19, 20)
⇝ 18?���
19?���20?
⇝
45
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
Merge: E1 ⊕conservative E2
(x↦19) ⊕conservative (x↦20) undefined
Enables a PutGet theorem
46
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
Merge: E1 ⊕conservative E2
(x↦19) ⊕conservative (x↦20) undefined
Enables a PutGet theorem
Merge: E1 ⊕optimistic E2
(x↦19) ⊕ optimistic (x↦20) = 19 or 20 (or 18) Enables many desirable interactions
47
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ 18 ) ⊢ (x, x)) ⇒'(18, 18)
((x ↦ 19 ) ⊢ (x, x)) ⇐' (19, 20)
⇝ 18?���
19?���20?
⇝
48
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
(– ⊢ let x = 18 in (x, x)) ⇒'(18, 18)
(– ⊢ let x = 18 in (x, x)) ⇐' (19, 20)
⇝ 18?���
19?���20?
⇝
Ask user to choose
49
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
50
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
⇝
(– ⊢ ) ⇒ let f = λx. x ++ "18"���in f "B "
"B 18"
"Bx 19"
51
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((f ↦ λx. x ++ "18") ⊢ f "B ") ⇒ "B 18"
"Bx 19"
⇝
52
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ "B ") ⊢ x ++ "18") ⇒ "B 18"
⇝
"Bx 19"
53
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((x ↦ "B ") ⊢ x ++ "18") ⇒
((x ↦ "Bx ") ⊢ x ++ "19") ⇐
"B 18"
⇝
"Bx 19"
"data" "code"
54
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
((f ↦ λx. x ++ "19") ⊢ f "Bx ") ⇐
"B 18" ((f ↦ λx. x ++ "18") ⊢ f "B ") ⇒
⇝
"Bx 19"
"data" "code"
55
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
v ::= c | [E] λx.e | (v1, v2)
E ::= – | (E, x↦v)
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
"B 18" (– ⊢ ) ⇒ let f = λx. x ++ "18"���in f "B "
let f = λx. x ++ "19"���in f "Bx "
(– ⊢ ) ⇐
⇝
"Bx 19"
"data" "code"
56
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
57
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
(– ⊢ "B " ++ "18") ⇒ "B 18" ⇝
"Bx 19"
58
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
(– ⊢ "B " ++ "18") ⇒
(– ⊢ "Bx " ++ "19") ⇐'
"B 18" ⇝
"Bx 19"
Primitive lens: ((++)get , (++)put)
59
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
| appLens (eget, eput) ex
(– ⊢ "B " ++ "18") ⇒
(– ⊢ "Bx " ++ "19") ⇐'
"B 18" ⇝
"Bx 19"
Libraries and users can���define custom lenses
Primitive lens: ((++)get , (++)put)
60
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
| appLens (eget, eput) ex
61
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
| appLens (eget, eput) ex
Bidirectional Programs���with are Lenses
62
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐'v'
⇝ ion
e ::= c | λx.e | x | (e1, e2) | e1 e2 | …
| appLens (eget, eput) ex
Bidirectional Programs���with are Lenses
63
Sketch-n-Sketch
64
Sketch-n-Sketch
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐ 'v'
⇝
65
Sketch-n-Sketch
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐ 'v'
⇝Elm-like PL +
66
Sketch-n-Sketch
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐ 'v'
⇝Elm-like PL + HTML GUI
67
Sketch-n-Sketch
(E ⊢ e') ⇒'v'
(E' ⊢ e') ⇐ 'v'
⇝Elm-like PL + HTML GUI
Demo
Bidirectional Evaluation
OOPSLA 2018
Bidirectional Programs���with are Lenses
68
Bidirectional Evaluation
OOPSLA 2018
A Bidirectional Krivine Evaluator
Bx 2019
69
70
Bidirectional CBV Evaluation
71
Bidirectional CBV Evaluation
72
Bidirectional CBV Evaluation
Most rules���are "mechanical"
73
Bidirectional CBV Evaluation
Most rules���are "mechanical"
App rule calls���forward evaluator
74
Bidirectional CBV Evaluation
Most rules���are "mechanical"
App rule calls���forward evaluator
75
76
Call-by-Value
Evaluate function to closure
Evaluate argument to value
77
Call-by-Value
Evaluate function to closure
Evaluate argument to value
Call-by-Name
Delay argument evaluation
78
Call-by-Value
Evaluate function to closure
Evaluate argument to value
Call-by-Name
Delay argument evaluation
Krivine Machine (for CBN)
Delay function and argument:
79
Call-by-Value
Evaluate function to closure
Evaluate argument to value
Call-by-Name
Delay argument evaluation
1Krivine Machine (for CBN)
Delay function and argument:
Add all args to stack… 1
80
Call-by-Value
Evaluate function to closure
Evaluate argument to value
Call-by-Name
Delay argument evaluation
Krivine Machine (for CBN)
Delay function and argument:
Add all args to stack…
"CBN apply" left-to-right
1
2
1
2
81
82
Bidirectional Krivine Evaluation
83
Bidirectional Krivine Evaluation
All rules, including���function application,���
are "mechanical"
Backward evaluator���does not call forward���
evaluator at all!
84
85
Future Work: Bi-Eval as a BX
Mechanically derive backward���evaluators (or abstract machines)?
86
Future Work: Bi-Eval as a BX
Mechanically derive backward���evaluators (or abstract machines)?
Scale design and implementation���
of bi-evaluation to larger languages���
87
Future Work: Bi-Eval as a BX
Mechanically derive backward���evaluators (or abstract machines)?
Scale design and implementation���
of bi-evaluation to larger languages������
Bidirectional JavaScript���λ-calc + ref + proto objects + label/break + exceptions
88
Related Work Bidirectional Evaluation
89
Func. Program Slicing [Perera et al., ICFP 2012]
Forward evaluator records full trace for output value
Backward evaluator slices exp. based on "don't-care" sub-values
Related Work Bidirectional Evaluation
90
Func. Program Slicing [Perera et al., ICFP 2012]
HOBiT [Matsuda and Wang, ESOP 2018]
Forward evaluator records full trace for output value
Backward evaluator slices exp. based on "don't-care" sub-values
Instead of lens combinators, staged evaluator for λ-calculus
First evaluation stage eliminates function calls (e1 e2)
Bidirectional evaluation for "residual" first-order programs
More direct support for "branch switching" than our approach
Related Work Bidirectional Evaluation
Bidirectional Evaluation
OOPSLA 2018
Bidirectional Programs���with are Lenses
91
Bidirectional Evaluation
OOPSLA 2018
A Bidirectional Krivine Evaluator
Bx 2019
Towards���Bi-Eval "For Free"
92
github.com/MikaelMayer/Editor
Bidirectional Evaluation
OOPSLA 2018
A Bidirectional Krivine Evaluator
Bx 2019
ravichugh.github.io/sketch-‐n-‐sketch
Sketch-n-Sketch Tharzen Editor
github.com/MikaelMayer/Editor
Bidirectional Evaluation
OOPSLA 2018
A Bidirectional Krivine Evaluator
Bx 2019
Thanks!
ravichugh.github.io/sketch-‐n-‐sketch
Sketch-n-Sketch
@MikaelMayer @ravi_chugh
Tharzen Editor