Presentation is loading. Please wait.

Presentation is loading. Please wait.

Compiling Real-Time Functional Reactive Programming (RT-FRP)

Similar presentations


Presentation on theme: "Compiling Real-Time Functional Reactive Programming (RT-FRP)"— Presentation transcript:

1 Compiling Real-Time Functional Reactive Programming (RT-FRP)
Dana N. Xu and Siau-Cheng Khoo National University of Singapore 2/19/2019

2 Compilation Partial evaluation Tupling Contribution:
RT-FRP program Functional Code Partial evaluation Automata Code We develop new techniques in PE and Tupling for compiling to automaton. Tupling Tupled Automaton Code Contribution: Systematic compilation via high-level source to source transformation

3 Contents Reactive System Introduction to RT-FRP
Translating RT-FRP to Functional Code Compiling Functional Code to Automaton Code Conclusion and Future Work 2/19/2019

4 Reactive System Reactive systems have to react to an physical environment which cannot wait. It requires cost (Time & Space) of running a program to be bounded and known before run-time. 2/19/2019

5 Contents Reactive System Introduction to RT-FRP
Translating RT-FRP to Functional Code Compiling Functional Code to Automata Code Conclusion and Future Work 2/19/2019

6 RT-FRP Reactive Part Base Language
Captures the essential ingredients of FRP programs Allows recursion and higher order functions Resource-bounded (both time and space) Base Language Choose a terminating and resource-bounded language FRP consists of combinators to express reactivity to events. Base Language is for programmer specified activities. 2/19/2019

7 RT-FRP Syntax e ::= x | c | () | (e1, e2) | e |  | x.e | e1 e2
v ::= c | () | (v1, v2) | v |  | x.e a. Base language syntax s, ev ::= input | time | ext e | delay v s | let snapshot x  s1 in s2 | s1 switch on x  ev in s2 | let continue {kj xj = uj } in s | u u ::= s until <evj  kj> b. Reactive language syntax Input: a stream of values from environment. Time: a stream of clock values Figure 2. RT-FRP language syntax 2/19/2019

8 Example 1 - The when operator
when s = let snapshot x1  s in let snapshot x2  delay False s in ext (if x2x1 then () else ) x1 x2 when s Rising edge 2/19/2019

9 Contents Reactive System Introduction to RT-FRP
Translating RT-FRP to Functional Code Compiling Functional Code to Automata Code Conclusion and Future Work 2/19/2019

10 Event and Behavior in RT-FRP
type Behavior a = [Time]  [a] Event a  Behavior (Maybe a) data Maybe a = Nothing | Just a type Event a = [Time]  [Maybe a] Behavior – continuous time-varying behaviors Event – discrete event-based reactivity time t1 t2 t3 t4 t5 t6 t7 b v1 v2 v3 v4 v5 v6 v7 e j1 j4 j5 j7 2/19/2019

11 Stream Based Implementation
time :: Behavior Time time = \ts -> ts delay :: a -> Behavior a -> Behavior a delay v s = \ts -> v:(s ts) ==> :: Event a -> (a->b) -> Event b .|. :: Event a -> Event a -> Event a untilB :: Behavior a -> Event (Behavior a) -> Behavior a switcher :: Behavior a -> 2/19/2019

12 Lifting Lifting values/operations at base level to
stream of values/operations at reactive level. Example 1 lift0 = constantB constantB 5 = [5, 5, 5, …] Example 2 w1 = let snapshot x <- time in ext (x+1) w1 = lift1 (\x -> x+1) time $ is a Haskell infix operator. This is the specific language used in domain specific language. 2/19/2019

13 Translating RT-FRP to Functional Code
[]tr :: RExp -> VEnv -> BExp [ext e]tr  = liftk (\v1..vk. e) w1..wk where ([v1..vk], [w1..wk]) =lookup e  [delay v s]tr  = delay v s’ where s’ = [s]  2/19/2019

14 Compiling RT-FRP to Functional Code
[let snapshot x s1 s2]  = … [time]  = time [s1 switch on x ev s2]  = … [s until <evj => kj>j=1..n]  = … [let continue {kj xj = uj}j=1..n in s]  = … 2/19/2019

15 Equivalent Functional Representation at Abstract Level
z = let snapshot a  delay True x in let snapshot b  delay True z in let snapshot c  input in ext (if a then b else ((a and b) or c)) z = lift3 (\a->\b->\c-> if a then b else ((a && b) || c)) (delay True x) (delay True z) input x = let snapshot a  delay True x in let snapshot b  z in ext (if a then False else b) x = lift2 (\a->\b->if a then False else b) (delay True x) z n = let snapshot a  delay True x in let snapshot b  delay 0 n in ext (if a then 0 else b+1) n = lift2 (\a->\b->if a then 0 else b+1) (delay True x) (delay 0 n) Translate to Translate to Translate to 2/19/2019

16 Contents Reactive System & Synchronous Language Introduction to RT-FRP
Translating RT-FRP to Functional Code Compiling Functional Code to Automata Code Conclusion and Future Work 2/19/2019

17 Our Algorithm to the body of the definition of a signal
Generalize all constants that may result in infinite variations. Apply a.Define configuration with state variables b.Instantiate signals c.Unfold & Unify d.Fold or goto 2a to the body of the definition of a signal 2/19/2019

18 From Previous Example z = lift3 (\a->\b->\c->
if a then b else ((a && b) || c)) (delay True x) (delay True z) input x = lift2 (\a->\b->if a then False else b) (delay True x) z n = lift2 (\a->\b->if a then 0 else b+1) (delay True x) (delay 0 n) 2/19/2019

19 Generalize Integer Constants
n = lift2 (\a->\b->if a then 0 else b+1) (delay True x) (delay 0 n) nconfig-1[c1,c2,c3]: n = lift2 (\a->\b->if a then c1 else b+c2) (delay True x) (delay c3 n) 2/19/2019

20 Instantiate signals Instantiate: x = delay x# x_ n = delay n# n_ [1]
n = lift2 (\a->\b->if a then c1 else b+c2) (delay True x) (delay c3 n) (delay True (delay x# x_)) (delay c3 (delay n# n_)) 2/19/2019

21 Unfold Once and Partial Evaluate
The unfolding rule used is : lift2 (\a->\b -> e) (delay v1 v) (delay w1 w) => delay e[v1/a,w1/b] (lift2 (\a->\b -> e) v w) n = lift2 (\a->\b->if a then c1 else b+c2) (delay True (delay x# x_)) (delay c3 (delay n# n_)) n = delay c1 (lift2 (\a->\b->if a then c1 else b+c2) (delay x# x_) (delay n# n_)) [2] 2/19/2019

22 Unification n = delay n# n_ [1]
n = delay c1 (lift2 (\a->\b->if a then c1 else b+c2) (delay x# x_) (delay n# n_)) [2] n= delay c1 n_ n_ = (lift2 (\a->\b->if a then c1 else b+c2) (delay x# x_) (delay c1 n_)) 2/19/2019

23 Adjust Time Backward (Future  Current)
n_ = (lift2 (\a->\b->if a then c1 else b+c2) (delay x# x_) (delay c1 n_)) n = (lift2 (\a->\b->if a then c1 else b+c2) (delay xb x) (delay c1 n)) x# => xb x_ => x n_ => n 2/19/2019

24 Try Folding Folding fails
n = (lift2 (\a->\b->if a then c1 else b+c2) (delay xb x) (delay c1 n)) nconfig-1[c1,c2,c3]: n = lift2 (\a->\b->if a then c1 else b+c2) (delay True x) (delay c3 n) Folding fails 2/19/2019

25 Define a New Configuration
n = (lift2 (\a->\b->if a then c1 else b+c2) (delay xb x) (delay c1 n)) n = delay c1 nconfig-2[c1,c2,c1] nconfig-2[b1,b2,b3]: n = (lift2 (\a->\b->if a then b1 else b+b2) (delay xb x) (delay b3 n)) from n_ original n 2/19/2019

26 Instantiate Instantiate: x = delay x# x_ n = delay n# n_
n =(lift2 (\a->\b->if a then c1 else b+c2) (delay xb x) (delay c3 n) (delay xb (delay x# x_)) (delay c3 (delay n# n_))) 2/19/2019

27 Instantiate Unknown Boolean
case xb == False: n =(lift2 (\a->\b->if a then c1 else b+c2) (delay False (delay x# x_)) (delay c3 (delay n# n_))) n = delay (c3+c2) (lift2 (\a->\b->if a then c1 else b+c2) (delay x# x_) (delay n# n_)) {unification with instantiation n#=c3+c2} (delay x# x_) (delay (c3+c2) n_)) n = delay (c3+c2) nconfig-2[c1,c2,c3+c2] 2/19/2019

28 (cont.) case xb == True: n =(lift2 (\a->\b->if a then c1 else b+c2) (delay True (delay x# x_)) (delay c3 (delay n# n_))) n = delay c1 (lift2 (\a->\b->if a then c1 else b+c2) (delay x# x_) (delay n# n_)) {unification with instantiation n#=c1} (delay x# x_) (delay c1 n_)) n = delay c1 nconfig-2[c1,c2,c1] 2/19/2019

29 Automaton for n nconfig-1[c1,c2,c3]: n=delay c1 nconfig-2[c1,c2,c1]
case xb = False n=delay (c3+c2) nconfig-2[c1,c2,c3+c2] case xb = True Each state has memory. For each transition, the current value of the signal is emitted. Each configuration has its own distinct set of state variables. 2/19/2019

30 Automata for n, x and z 2/19/2019

31 Tupling To combine multiple automata into a single automaton Benefits
More efficient Less control logic More specialization across automata 2/19/2019

32 Tupling Combine three signals together mconfig-111[c1,c2,c3]
(n,x,z)=(nconfig-1[c1,c2,c3],xconfig-1,zconfig-1) = delay (c1,False,True) (nconfig-2[c1,c2,c1],xconfig2,zconfig-2) mconfig-222[c1,c2,c1] Tupling them to form a single automaton so that less logic and computation. 2/19/2019

33 Define, Unfold and Fold (twice)
mconfig-222[c1,c2,c3] st xb =False, zb =True (n,x,z)=(nconfig-2[c1,c2,c3],xconfig-2,zconfig-2) : = delay (c3+c2,True,True) mconfig-233[c1,c2,c3+c2] mconfig-233[c1,c2,c3] st xb =True, zb =True (n,x,z) = (nconfig-2[c1,c2,c3],xconfig-3,zconfig-3) = delay (c1,False,True) mconfig-223[c1,c2,c1] Check correctness later 2/19/2019

34 Define, Unfold and Fold mconfig-223[c1,c2,c3] st xb = False, zb = True
(n,x,z)= (nconfig-2[c1,c2,c3],xconfig-2,zconfig-3) : = delay (c3+c2,z#,input#) mconfig-233a[c1,c2,c3+c2] 2/19/2019

35 Define, Unfold and Fold mconfig-233a[c1,c2,c3] st x#=z#=input# (n,x,z)
= (nconfig-2[c1,c2,c3],xconfig-3,zconfig-3) case x#=z#=False = delay (c3+c2,z#,input#) (nconfig-2[c1,c2,c3+c2],xconfig-3,zconfig-3) =delay (c3+c2,z#,input#) mconfig-233a[c1,c2,c3+c2] case x#=z#=True = delay (c1,False,True) (nconfig-2[c1,c2,c1],xconfig-2,zconfig-3) =delay (c1,False,True) mconfig-223[c1,c2,c1] 2/19/2019

36 Final Tupled Automaton
mconfig-111[c1,c2,c3]: (n,x,z)= delay (c1,False,True) mconfig-222[c1,c2,c1] mconfig-222[c1,c2,c3]: (n,x,z)= delay (c3+c2,True,True) mconfig-233[c1,c2,c3+c2] mconfig-233[c1,c2,c3]: mconfig-223[c1,c2,c1] mconfig-223[c1,c2,c3]: (n,x,z)= delay (c3+c2,input#,input#) mconfig-233a[c1,c2,c3+c2] mconfig-233a[c1,c2,c3] st x#=z#=input# (n,x,z) = (nconfig-2[c1,c2,c3],xconfig-3,zconfig-3) case x#=z#=False = delay (c3+c2,input#,input#) case x#=z#=True =delay (c1,False,True) mconfig-223[c1,c2,c1] 2/19/2019

37 Final Tupled Automaton
2/19/2019

38 Automata for n, x and z 2/19/2019

39 Final Tupled Automaton
2/19/2019

40 Conclusion Introduce an approach to building reactive systems based on RT-FRP A two-stage compiler for RT-FRP RT-FRP  Functional Code Functional Code  Automaton Partial Evaluation Tupling 2/19/2019

41 Future Work Re-design RT-FRP event-driven deterministic concurrent
compile to hardware 2/19/2019

42 Unfolding Rules .|. :: Event a -> Event a -> Event a
(delay  v) .|. (delay w1 w) => delay w1 (v .|. w) (delay (Just a) v) .|. (delay w1 w) => delay (Just a) (v .|. w) ==> :: Event a -> (a->b) -> Event b (delay  v) ==> f => (delay  (v ==> f)) (delay (Just a) v) ==> f => (delay (Just (f a))) bot) 2/19/2019

43 Unfolding Rules lift2 (\a->\b -> e) (delay v1 v) (delay w1 w)
=> delay e[v1/a,w1/b] (lift (\a b -> e) v w) switcher :: Behavior a->Event (Behavior a)->Behavior a switcher (delay v1 v) (delay  w) => delay v1 (switcher v w) switcher (delay v1 v) (delay (Just k) w) => delay v1 (switcher k w) untilB :: Behavior a->Event (Behavior a)->Behavior a untilB (delay v1 v) (delay  w) => delay v1 (untilB v w) untilB (delay v1 v) (delay (Just k) w) => delay v1 k 2/19/2019

44 Compiling RT-FRP to Functional Code
extr[s]   = let v1..vn = freevar s -  if (n=0) then [s]   else lams v1..vn where lams = \ v1..vn -> [s]   2/19/2019

45 RT-FRP Example 1 s1 = let snapshot x  time in ext (sin x) time value
2/19/2019

46 FRP vs. RT-FRP FRP RT-FRP type Behavior a = Time  a
type Event a = [(Time, a)] RT-FRP Event a  Behavior (Maybe a) data Maybe a = Nothing | Just a type Behavior a = [Time]  [a] type Event a = [Time]  [Maybe a] Behavior – continuous time-varying behaviors Event – discrete event-based reactivity 2/19/2019

47 Stream Based Implementation
==> :: Event a -> (a->b) -> Event b e1 ==> f = \ts  loop ts (e1 ts) where loop (_:ts) (Nothing:ys) = Nothing:(loop ts ys) loop (_:ts) (Just a:ys) = (Just (f a)):(loop ts ys) fe ==> f = map (map f).fe 2/19/2019

48 Two Schemes for Reactive System Implementation
<Initialize Memory> foreach input_event do <Compute Outputs> <Update Memory> end foreach period do <Read Inputs> a. “Event driven” b. “Sampling” Figure 1. Execution schemes for reactive systems 2/19/2019

49 Stream Based Implementation
time :: Behavior Time time = \ts -> ts delay :: a -> Behavior a -> Behavior a delay v s = \ts -> v:(s ts) ==> :: Event a -> (a->b) -> Event b e ==> f = map (map f) . e 2/19/2019

50 Stream Based Implementation
==> :: Event a -> (a->b) -> Event b e1 ==> f = \ts  loop ts (e1 ts) where loop (_:ts) (Nothing:es) = Nothing:(loop ts es) loop (_:ts) (Just a:es) = (Just (f a)):(loop ts es) 2/19/2019

51 Stream Based Implementation
.|. :: Event a -> Event a -> Event a e1 .|. e2 = \ts -> zipWith aux (e1 ts) (e2 ts) where aux Nothing Nothing = Nothing aux (Just x) _ = Just x aux _ (Just x) = Just x 2/19/2019

52 Stream Based Implementation
untilB :: Behavior a -> Event (Behavior a) -> Behavior a b `untilB` e = \ts -> loop ts (b ts) (e ts) where loop (_:ts’) (x:xs’) (Nothing:mb) = x:(loop ts’ xs’ mb) loop ts (x:xs’)(Just bn:_) = x:(bn ts) 2/19/2019

53 Stream Based Implementation
switcher :: Behavior a -> Event (Behavior a) -> Behavior a s `switcher` e = \ts -> loop ts (s ts) (e ts) where loop (_:ts’) (x:xs’) (Nothing:mb) = x:(loop ts’ xs’ mb) loop (_:ts’) (x:xs’) (Just bn:mb) = x:(loop ts’ (bn ts’) mb) 2/19/2019

54 Compiling RT-FRP to Functional Code
[let snapshot x s1 s2]   = [s2] ’  where x’ =[s1] ’  ’ =   {(x,x’)} [time]   = time 2/19/2019

55 Compiling RT-FRP to Functional Code
[s1 switch on x ev s2]   = switcher s1’ (ev’ ==> \x -> s2’) where ev’ =[ev]   s1’ =[s1]   s2’ =[s2]   2/19/2019

56 Compiling RT-FRP to Functional Code
[s until <evj => kj>j=1..n]   s’ `untilB` (ev1’ ==> k1’ … .|. evj’ ==> kj’ … .|. evn’ ==> kn’) where evi’ = [evi]   s’ = [s]   kj’ = lookup  kj 2/19/2019

57 Compiling RT-FRP to Functional Code
[let continue {kj xj = uj}j=1..n in s]   = [s]  ’ where ’ =   {(kj,kj’)}j=1..n kj’ = \ xj -> [uj]  ’ 2/19/2019

58 RT-FRP Examples 2 S3 = (ext 0) switch on x  ev in (ext x)
   2 … 2/19/2019

59 Synchronous Programming
Automaton Simple structure Good coverage Efficient Difficult to design by hand  Synchronous Programming High level  Modularity  Simple to re-use and compose  Efficiency is not sacrificed  The states are the valuations of the memory and each reaction corresponds to a transition of the automaton. Difficult to design automaton by hand, especially for complex systems with a large number of states. Performance of using synchronous programming is as good as carefully hand-written code. 2/19/2019

60 Compilation RT-FRP program Why intermediate functional code is needed?
Easier to validate its correctness Allows High-level s-to-s transformation Functional Code Partial Evaluation to propagate constant values to perform more aggressive specialization Automata Code Tupling to combine mutually dependent automata into a composite automaton Why Automaton? Simple, efficient, expressive [Halbwachs:CAV’98] Tupled Automaton Code 2/19/2019

61 Lifting fb $* xb = \ts  zipWith ($) (fb ts) (xb ts))
lift0 = constantB lift1 f b1 = lift0 f $* b1 lift2 f b1 b2 = lift1 f b1 $* b2 lift3 f b1 b2 b3 = lift2 f b1 b2 $* b3 : $ is a Haskell infix operator. This is the specific language used in domain specific language. 2/19/2019

62 Code in RT-FRP(Example)
z = let snapshot a  delay True x in let snapshot b  delay True z in let snapshot c  input in ext (if a then b else ((a and b) or c)) x = let snapshot a  delay True x in let snapshot b  z in ext (if a then False else b) n = let snapshot a  delay True x in let snapshot b  delay 0 n in ext (if a then 0 else b+1) 2/19/2019


Download ppt "Compiling Real-Time Functional Reactive Programming (RT-FRP)"

Similar presentations


Ads by Google