-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathExamples.hs
111 lines (94 loc) · 3.67 KB
/
Examples.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
module Gibbon.L1.Examples where
import Data.Map as M
import Gibbon.L1.Syntax
--------------------------------------------------------------------------------
treeTy :: Ty1
treeTy = PackedTy "Tree" ()
treeDD :: DDefs (UrTy ())
treeDD = (fromListDD [DDef "Tree" []
[ ("Leaf",[(False,IntTy)])
, ("Node",[(False,treeTy)
,(False,treeTy)])]])
mkAdd1Prog :: Exp1 -> Maybe (Exp1, Ty1) -> Prog1
mkAdd1Prog bod mainExp = Prog treeDD
(M.fromList [("add1",mkAdd1Fun bod)])
mainExp
mkAdd1Fun :: Exp1 -> FunDef1
mkAdd1Fun bod = FunDef "add1" ["tr"] ([treeTy],treeTy) bod (FunMeta Rec NoInline False)
----------------
-- | The basic form of the add1 program where recursions happen
-- immediately as arguments to the data-constructor.
add1Prog :: Prog1
add1Prog = mkAdd1Prog exadd1Bod Nothing
exadd1Bod :: Exp1
exadd1Bod =
CaseE (VarE "tr") $
[ ("Leaf", [("n",())],
PrimAppE AddP [VarE "n", LitE 1])
, ("Node", [("x",()),("y",())],
DataConE () "Node"
[ AppE "add1" [] [VarE "x"]
, AppE "add1" [] [VarE "y"]])
]
exadd1BodLetLeft :: Exp1
exadd1BodLetLeft =
CaseE (VarE "tr") $
[ ("Leaf", [("n",())], PrimAppE AddP [VarE "n", LitE 1])
, ("Node", [("x",()),("y",())],
LetE ("x2",[], treeTy, AppE "add1" [] [VarE "x"]) $
LetE ("y2",[], treeTy, AppE "add1" [] [VarE "y"]) $
DataConE () "Node"
[ VarE "x2", VarE "y2"])
]
-- | A more challenging case where recursions are performed right-to-left
exadd1BodLetRight :: Exp1
exadd1BodLetRight =
CaseE (VarE "tr") $
[ ("Leaf", [("n",())], PrimAppE AddP [VarE "n", LitE 1])
, ("Node", [("x",()),("y",())],
LetE ("y2",[], treeTy, AppE "add1" [] [VarE "y"]) $
LetE ("x2",[], treeTy, AppE "add1" [] [VarE "x"]) $
DataConE () "Node"
[ VarE "x2", VarE "y2"])
]
-- | Add1 program with let bindings, recurring in left-to-right order.
add1ProgLetLeft :: Prog1
add1ProgLetLeft = mkAdd1Prog exadd1BodLetLeft Nothing
-- | Add1 program with let bindings, recurring in right-to-left order.
add1ProgLetRight :: Prog1
add1ProgLetRight = mkAdd1Prog exadd1BodLetRight Nothing
-- | An even more challenging case where there is an (apparent) data
-- dependency where x2 depends on y2.
add1ProgChallenge :: Prog1
add1ProgChallenge =
Prog treeDD
(M.fromList [ ("add1",mkAdd1Fun bod)
, ("pred", FunDef "pred" ["tr"] ([treeTy], BoolTy)
(CaseE (VarE "tr") $
[ ("Leaf", [("n",())], PrimAppE MkTrue [])
, ("Node", [("x",()),("y",())], PrimAppE MkFalse [])])
(FunMeta Rec NoInline False))])
Nothing
where
bod =
CaseE (VarE "tr") $
[ ("Leaf", [("n",())], PrimAppE AddP [VarE "n", LitE 1])
, ("Node", [("x",()),("y",())],
LetE ("y2",[], treeTy, AppE "add1" [] [VarE "y"]) $
LetE ("x2",[], treeTy,
(IfE (AppE "pred" [] [VarE "y2"])
(AppE "add1" [] [VarE "x"])
(AppE "add1" [] [VarE "x"]))) $
DataConE () "Node" [ VarE "x2", VarE "y2"])
]
-- | This program is a challenge because a packed value flows to two destinations.
add1ProgSharing :: Prog1
add1ProgSharing = Prog treeDD (M.fromList [("add1",mkAdd1Fun bod)]) Nothing
where
bod =
CaseE (VarE "tr") $
[ ("Leaf", [("n",())], PrimAppE AddP [VarE "n", LitE 1])
, ("Node", [("x",()),("y",())],
LetE ("x2",[], treeTy, AppE "add1" [] [VarE "x"]) $
DataConE () "Node" [ VarE "x2", VarE "x2"])
]