1
1
{-# LANGUAGE DataKinds #-}
2
2
{-# LANGUAGE DeriveAnyClass #-}
3
3
{-# LANGUAGE DeriveGeneric #-}
4
+ {-# LANGUAGE LambdaCase #-}
4
5
{-# LANGUAGE OverloadedStrings #-}
5
6
{-# LANGUAGE TupleSections #-}
6
7
7
8
module Main (main ) where
8
9
9
- import Control.Monad (unless )
10
+ import Control.Monad (unless , (>=>) )
11
+ import Control.Monad.Error.Class (throwError )
10
12
import Control.Monad.IO.Class (liftIO )
11
13
import Control.Monad.Logger (runLogger' )
14
+ import Control.Monad.State (State )
15
+ import qualified Control.Monad.State as State
12
16
import Control.Monad.Trans (lift )
13
- import Control.Monad.Error.Class (throwError )
14
17
import Control.Monad.Trans.Except (ExceptT (.. ), runExceptT )
15
18
import Control.Monad.Trans.Reader (runReaderT )
16
19
import qualified Data.Aeson as A
17
20
import Data.Aeson ((.=) )
18
21
import qualified Data.ByteString.Lazy as BL
19
22
import Data.List (foldl' )
23
+ import qualified Data.Map as M
20
24
import Data.String (fromString )
21
25
import Data.Text (Text )
22
26
import qualified Data.Text as T
@@ -30,12 +34,14 @@ import qualified Language.PureScript.CodeGen.JS as J
30
34
import qualified Language.PureScript.CoreFn as CF
31
35
import qualified Language.PureScript.Errors.JSON as P
32
36
import qualified Language.PureScript.Interactive as I
37
+ import qualified Language.PureScript.TypeChecker.TypeSearch as TS
33
38
import System.Environment (getArgs )
34
39
import System.Exit (exitFailure )
35
40
import System.FilePath ((</>) )
36
41
import System.FilePath.Glob (glob )
37
42
import qualified System.IO as IO
38
43
import System.IO.UTF8 (readUTF8File )
44
+ import qualified Text.Parsec.Combinator as Parsec
39
45
import Web.Scotty
40
46
import qualified Web.Scotty as Scotty
41
47
@@ -90,6 +96,47 @@ server bundled externs initEnv port = do
90
96
Scotty. json $ A. object [ " error" .= err ]
91
97
Right comp ->
92
98
Scotty. json $ A. object [ " js" .= comp ]
99
+ get " /search" $ do
100
+ query <- param " q"
101
+ case tryParseType query of
102
+ Nothing -> Scotty. json $ A. object [ " error" .= (" Cannot parse type" :: Text ) ]
103
+ Just ty -> do
104
+ let ty' = replaceTypeVariablesAndDesugar ty
105
+ let results = TS. typeSearch (Just [] ) initEnv (P. emptyCheckState initEnv) ty'
106
+ Scotty. json $ A. object [ " results" .= A. object [ P. showQualified P. runIdent k .= P. prettyPrintType v
107
+ | (k, v) <- take 20 (M. toList results)
108
+ ]
109
+ ]
110
+
111
+ -- | (Consistently) replace unqualified type constructors and type variables with unknowns.
112
+ --
113
+ -- Also remove the @ParensInType@ Constructor (we need to deal with type operators later at some point).
114
+ replaceTypeVariablesAndDesugar :: P. Type -> P. Type
115
+ replaceTypeVariablesAndDesugar ty = State. evalState (P. everywhereOnTypesM go ty) (0 , M. empty) where
116
+ go = \ case
117
+ P. ParensInType ty -> pure ty
118
+ P. TypeConstructor (P. Qualified Nothing tyCon) -> do
119
+ (next, m) <- State. get
120
+ case M. lookup (Left tyCon) m of
121
+ Nothing -> do
122
+ let ty = P. TUnknown next
123
+ State. put (next + 1 , M. insert (Left tyCon) ty m)
124
+ pure ty
125
+ Just ty -> pure ty
126
+ P. TypeVar s -> do
127
+ (next, m) <- State. get
128
+ case M. lookup (Right s) m of
129
+ Nothing -> do
130
+ let ty = P. TUnknown next
131
+ State. put (next + 1 , M. insert (Right s) ty m)
132
+ pure ty
133
+ Just ty -> pure ty
134
+ other -> pure other
135
+
136
+ tryParseType :: Text -> Maybe P. Type
137
+ tryParseType = hush (P. lex " " ) >=> hush (P. runTokenParser " " (P. parsePolyType <* Parsec. eof))
138
+ where
139
+ hush f = either (const Nothing ) Just . f
93
140
94
141
bundle :: IO (Either Bundle. ErrorMessage String )
95
142
bundle = runExceptT $ do
0 commit comments