-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTests.hs
More file actions
131 lines (121 loc) · 4.77 KB
/
Tests.hs
File metadata and controls
131 lines (121 loc) · 4.77 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import Debug.RocketFuel
import Fliter.Miniplate
import Fliter.Parser
import Fliter.Semantics
import Fliter.Syntax
import Supercompiler
import Example
import Control.Monad
import Data.IORef
import System.Environment
import System.Exit
-- Under bounded evaluation;
-- 1. Runs a program `p` which may terminate with a value `v`.
-- 2. Supercompile first function in `p` and call new program
-- `q`.
-- 3. Runs the supercompiled program `q` which may terminate
-- with a value `w`.
-- 4. Passes if; supercompilation terminates *and* (running `p`
-- does not terminate *or* (`q` does terminate and `v == w`).
testSmallProg :: IORef (Int, Int) -> (Int, Prog t a) -> IO Bool
testSmallProg counters (i, p_) = do
let scLimit = 1000
let stepLimit = 1000
incCounter counters False
when (i `mod` 10000 == 0) $ putStrLn $ "(Checked " ++ show i ++ ")"
fillTank scLimit
let p = deTagProg $ unsafeEraseProg p_
let (m, t) = execFor stepLimit (nonRecInline p) initState
let q = sc p $ mkLam p
let failed_q = goesBingo q
let (n, u) = execFor stepLimit q initState
when (n < m) $ incCounter counters True
if failed_q
then do print $ fmap (const ()) p_
showExec t
putStrLn ""
fail $ "@" ++ show i ++ ": Failed on SC!"
else if t <| u
then if True -- (n <= m)
then return True
else do print $ nonRecInline $ fmap (const ()) p_
showExec t
putStrLn ""
print q
putStrLn ""
fail $ "@" ++ show i ++ ": Failed on optimisation! " ++ show m ++ " < " ++ show n
else do print $ fmap (const ()) p_
showExec t
putStrLn ""
print q
showExec u
putStrLn ""
fail $ "@" ++ show i ++ ": Failed on semantic preservation!"
incCounter counters switch = do
(total, improved) <- readIORef counters
let total' = if switch then total else total + 1
let improved' = if switch then improved + 1 else improved
total' `seq` improved' `seq` writeIORef counters (total', improved')
testBigProg :: IORef (Int, Int) -> String -> IO Bool
testBigProg counters filePath = do
let scLimit = 10000
let stepLimit = 10000
fillTank scLimit
let p = deTagProg $ unsafeEraseProg $ parseProg filePath
let (m, t) = execFor stepLimit (nonRecInline p) initState
let q = sc p $ mkLam p
let failed_q = goesBingo q
let (n, u) = execFor stepLimit q initState
when (n < m) $ incCounter counters True
if failed_q
then do showExec t
putStrLn ""
fail $ show filePath ++ ": Failed on SC!"
else if t <| u
then if True -- (n <= m)
then return True
else do showExec t
putStrLn ""
print q
putStrLn ""
fail $ show filePath ++ ": Failed on optimisation! " ++ show m ++ " < " ++ show n
else do showExec t
putStrLn ""
print q
showExec u
putStrLn ""
fail $ show filePath ++ ": Failed on semantic preservation!"
showExec t = case t of
Crash -> putStrLn $ "Crashed!"
Halt v -> putStrLn $ "Terminated: " ++ show v
Cont v -> putStrLn $ "Non-productive."
mkLam :: Prog () a -> (Id, Func () a)
mkLam (Prog ps) = (fId, Lam ar $ () :> ((() :> Fun fId []) :@ [Bnd i | i <- [0..ar - 1]]))
where ps' = filter ((/= "main") . fst) ps
(fId, Lam ar _) = if null ps' then head ps else last ps'
goesBingo :: Prog t a -> Bool
goesBingo (Prog p) = or [ True
| (_, Lam _ x) <- p
, Con "<BINGO>" _ <- universe $ getRhs $ x ]
(<|) :: Exec (Expr () ()) (Expr () ()) -> Exec (Expr () ()) (Expr () ()) -> Bool
Crash <| _ = True
Cont _ <| _ = True
Halt v <| Halt w = v == w
Halt v <| _ = False
benchmarks = ["Benchmarks/Fib.hs", "Benchmarks/Queens.hs"]
main = do
putStrLn "Testing generated programs:"
counters <- newIORef (0, 0)
as <- getArgs
guard $ (not.null) as
ps <- parseProgs $ head as
mapM_ (testSmallProg counters) $ zip [1..] ps
(total, improved) <- readIORef counters
putStrLn $ "Tested " ++ show total ++ " programs of which " ++
show improved ++ " strictly improved performance.\n"
putStrLn "Testing constructed programs:"
counters <- newIORef (0, 0)
mapM_ (testBigProg counters) benchmarks
(total, improved) <- readIORef counters
putStrLn $ "Tested " ++ show (length benchmarks) ++ " programs of which " ++
show improved ++ " strictly improved performance.\n"