2
2
{-# OPTIONS_GHC -Wwarn -fno-warn-orphans #-}
3
3
4
4
-- | Expression execution
5
- module Ide.Plugin.Eval.Code (Statement ,testRanges ,resultRange ,evalExtensions ,evalSetup ,evalExpr ,propSetup ,testCheck ,asStatements ) where
6
-
7
- import Data.Algorithm.Diff (Diff ,PolyDiff (.. ),getDiff )
8
- import qualified Data.List.NonEmpty as NE
9
- import Data.String (IsString )
10
- import qualified Data.Text as T
11
- import Development.IDE.Types.Location (Position (.. ), Range (.. ))
12
- import GHC (compileExpr )
13
- import GHC.LanguageExtensions.Type (Extension (.. ))
14
- import GhcMonad (Ghc , GhcMonad , liftIO )
15
- import Ide.Plugin.Eval.Types (Language (Plain ), Loc ,
16
- Located (Located ),
17
- Section (sectionLanguage ),
18
- Test (Example , Property , testOutput ),
19
- Txt , locate , locate0 )
20
- import InteractiveEval (runDecls )
21
- import Unsafe.Coerce (unsafeCoerce )
5
+ module Ide.Plugin.Eval.Code (Statement , testRanges , resultRange , evalExtensions , evalSetup , evalExpr , propSetup , testCheck , asStatements ) where
6
+
7
+ import Data.Algorithm.Diff (Diff , PolyDiff (.. ), getDiff )
8
+ import qualified Data.List.NonEmpty as NE
9
+ import Data.String (IsString )
10
+ import qualified Data.Text as T
11
+ import Development.IDE.Types.Location (Position (.. ), Range (.. ))
12
+ import GHC (compileExpr )
13
+ import GHC.LanguageExtensions.Type (Extension (.. ))
14
+ import GhcMonad (Ghc , GhcMonad , liftIO )
15
+ import Ide.Plugin.Eval.Types (
16
+ Language (Plain ),
17
+ Loc ,
18
+ Located (Located ),
19
+ Section (sectionLanguage ),
20
+ Test (Example , Property , testOutput ),
21
+ Txt ,
22
+ locate ,
23
+ locate0 ,
24
+ )
25
+ import InteractiveEval (runDecls )
26
+ import Unsafe.Coerce (unsafeCoerce )
22
27
23
28
-- | Return the ranges of the expression and result parts of the given test
24
29
testRanges :: Loc Test -> (Range , Range )
25
30
testRanges (Located line tst) =
26
- let startLine = line
27
- (exprLines, resultLines) = testLenghts tst
28
- resLine = startLine + exprLines
29
- in ( Range
30
- (Position startLine 0 )
31
- -- (Position (startLine + exprLines + resultLines) 0),
32
- (Position resLine 0 ),
33
- Range (Position resLine 0 ) (Position (resLine + resultLines) 0 )
34
- )
35
-
36
- -- | The document range where a test is defined
37
- -- testRange :: Loc Test -> Range
38
- -- testRange = fst . testRanges
31
+ let startLine = line
32
+ (exprLines, resultLines) = testLenghts tst
33
+ resLine = startLine + exprLines
34
+ in ( Range
35
+ (Position startLine 0 )
36
+ -- (Position (startLine + exprLines + resultLines) 0),
37
+ (Position resLine 0 )
38
+ , Range (Position resLine 0 ) (Position (resLine + resultLines) 0 )
39
+ )
40
+
41
+ {- | The document range where a test is defined
42
+ testRange :: Loc Test -> Range
43
+ testRange = fst . testRanges
44
+ -}
39
45
40
46
-- | The document range where the result of the test is defined
41
47
resultRange :: Loc Test -> Range
@@ -50,17 +56,17 @@ showDiffs :: (Semigroup a, IsString a) => [Diff a] -> [a]
50
56
showDiffs = map showDiff
51
57
52
58
showDiff :: (Semigroup a , IsString a ) => Diff a -> a
53
- showDiff (First w) = " WAS " <> w
59
+ showDiff (First w) = " WAS " <> w
54
60
showDiff (Second w) = " NOW " <> w
55
61
showDiff (Both w _) = w
56
62
57
63
testCheck :: (Section , Test ) -> [T. Text ] -> [T. Text ]
58
64
testCheck (section, test) out
59
- | null (testOutput test) || sectionLanguage section == Plain = out
60
- | otherwise = showDiffs $ getDiff (map T. pack $ testOutput test) out
65
+ | null (testOutput test) || sectionLanguage section == Plain = out
66
+ | otherwise = showDiffs $ getDiff (map T. pack $ testOutput test) out
61
67
62
68
testLenghts :: Test -> (Int , Int )
63
- testLenghts (Example e r) = (NE. length e, length r)
69
+ testLenghts (Example e r) = (NE. length e, length r)
64
70
testLenghts (Property _ r) = (1 , length r)
65
71
66
72
-- | A one-line Haskell statement
@@ -72,48 +78,49 @@ asStatements lt = locate (asStmts <$> lt)
72
78
asStmts :: Test -> [Txt ]
73
79
asStmts (Example e _) = NE. toList e
74
80
asStmts (Property t _) =
75
- [" prop11 = " ++ t, " (propEvaluation prop11 :: IO String)" ]
81
+ [" prop11 = " ++ t, " (propEvaluation prop11 :: IO String)" ]
76
82
77
83
-- | Evaluate an expression (either a pure expression or an IO a)
78
84
evalExpr :: GhcMonad m => [Char ] -> m String
79
85
evalExpr e = do
80
- res <- compileExpr $ " asPrint (" ++ e ++ " )"
81
- liftIO (unsafeCoerce res :: IO String )
86
+ res <- compileExpr $ " asPrint (" ++ e ++ " )"
87
+ liftIO (unsafeCoerce res :: IO String )
82
88
83
89
-- | GHC extensions required for expression evaluation
84
90
evalExtensions :: [Extension ]
85
91
evalExtensions =
86
- [ OverlappingInstances ,
87
- UndecidableInstances ,
88
- FlexibleInstances ,
89
- IncoherentInstances ,
90
- TupleSections
91
- ]
92
+ [ OverlappingInstances
93
+ , UndecidableInstances
94
+ , FlexibleInstances
95
+ , IncoherentInstances
96
+ , TupleSections
97
+ ]
92
98
93
99
-- | GHC declarations required for expression evaluation
94
100
evalSetup :: Ghc ()
95
101
evalSetup =
96
- mapM_
97
- runDecls
98
- [ " class Print f where asPrint :: f -> IO String" ,
99
- " instance Show a => Print (IO a) where asPrint io = io >>= return . show" ,
100
- " instance Show a => Print a where asPrint a = return (show a)"
101
- ]
102
+ mapM_
103
+ runDecls
104
+ [ " class Print f where asPrint :: f -> IO String"
105
+ , " instance Show a => Print (IO a) where asPrint io = io >>= return . show"
106
+ , " instance Show a => Print a where asPrint a = return (show a)"
107
+ ]
102
108
103
- -- | GHC declarations required to execute test properties
104
- propSetup :: [Loc [Char ]]
105
- propSetup =
106
- locate0
107
- [ " :set -XScopedTypeVariables -XExplicitForAll" ,
108
- " import qualified Test.QuickCheck as Q11" ,
109
- " propEvaluation p = Q11.quickCheckWithResult Q11.stdArgs p >>= error . Q11.output" -- uses `error` to get a multi-line display
110
- ]
109
+ {- | GHC declarations required to execute test properties
110
+
111
+ Example:
111
112
112
- {-
113
113
prop> \(l::[Bool]) -> reverse (reverse l) == l
114
114
+++ OK, passed 100 tests.
115
115
116
116
prop> \(l::[Bool]) -> reverse l == l
117
- *** Failed! Falsified (after 3 tests):
117
+ *** Failed! Falsified (after 6 tests and 2 shrinks ):
118
118
[True,False]
119
119
-}
120
+ propSetup :: [Loc [Char ]]
121
+ propSetup =
122
+ locate0
123
+ [ " :set -XScopedTypeVariables -XExplicitForAll"
124
+ , " import qualified Test.QuickCheck as Q11"
125
+ , " propEvaluation p = Q11.quickCheckWithResult Q11.stdArgs p >>= error . Q11.output" -- uses `error` to get a multi-line display
126
+ ]
0 commit comments