@@ -7,6 +7,7 @@ module Main (main) where
7
7
8
8
import Control.Monad (unless , foldM )
9
9
import Control.Monad.Error.Class (throwError )
10
+ import Control.Monad.IO.Class (liftIO )
10
11
import Control.Monad.Logger (runLogger' )
11
12
import qualified Control.Monad.State as State
12
13
import Control.Monad.Trans (lift )
@@ -15,25 +16,30 @@ import Control.Monad.Trans.Reader (runReaderT)
15
16
import Control.Monad.Writer.Strict (runWriterT )
16
17
import qualified Data.Aeson as A
17
18
import Data.Aeson ((.=) )
18
- import Data.Bifunctor (first , second )
19
+ import Data.Bifunctor (first , second , bimap )
19
20
import qualified Data.ByteString.Lazy as BL
20
21
import Data.Default (def )
21
22
import Data.Function (on )
23
+ import qualified Data.IORef as IORef
22
24
import Data.List (nubBy )
23
25
import qualified Data.List.NonEmpty as NE
24
26
import qualified Data.Map as M
25
27
import Data.Text (Text )
26
28
import qualified Data.Text as T
27
29
import qualified Data.Text.Encoding as T
30
+ import Data.Time.Clock (UTCTime )
28
31
import GHC.Generics (Generic )
29
32
import qualified Language.PureScript as P
30
33
import qualified Language.PureScript.CST as CST
31
34
import qualified Language.PureScript.CST.Monad as CSTM
32
35
import qualified Language.PureScript.CodeGen.JS as J
33
36
import qualified Language.PureScript.CodeGen.JS.Printer as P
34
37
import qualified Language.PureScript.CoreFn as CF
38
+ import qualified Language.PureScript.Docs.Types as Docs
35
39
import qualified Language.PureScript.Errors.JSON as P
36
40
import qualified Language.PureScript.Interactive as I
41
+ import qualified Language.PureScript.Make as Make
42
+ import qualified Language.PureScript.Make.Cache as Cache
37
43
import qualified Language.PureScript.TypeChecker.TypeSearch as TS
38
44
import qualified Network.Wai.Handler.Warp as Warp
39
45
import System.Environment (getArgs )
@@ -51,33 +57,90 @@ data Error
51
57
52
58
instance A. ToJSON Error
53
59
60
+ toCompilerErrors :: NE. NonEmpty CST. ParserError -> Error
61
+ toCompilerErrors = CompilerErrors . toJsonErrors . CST. toMultipleErrors " <file>"
62
+
63
+ toJsonErrors :: P. MultipleErrors -> [P. JSONError ]
64
+ toJsonErrors = P. toJSONErrors False P. Error
65
+
66
+ -- As of PureScript 0.14 we only need the `codegen` part of `MakeActions` to run
67
+ -- Try PureScript, because we already know all dependencies are compiled, we're
68
+ -- only building one module, we don't allow FFI declarations, and we want to
69
+ -- avoid writing to the file system as much as possible.
70
+ buildMakeActions :: IORef. IORef (Maybe JS ) -> Make. MakeActions Make. Make
71
+ buildMakeActions codegenRef =
72
+ Make. MakeActions
73
+ getInputTimestampsAndHashes
74
+ getOutputTimestamp
75
+ readExterns
76
+ codegen
77
+ ffiCodegen
78
+ progress
79
+ readCacheDb
80
+ writeCacheDb
81
+ outputPrimDocs
82
+ where
83
+ getInputTimestampsAndHashes :: P. ModuleName -> Make. Make (Either Make. RebuildPolicy (M. Map FilePath (UTCTime , Make. Make Cache. ContentHash )))
84
+ getInputTimestampsAndHashes _ = pure $ Right M. empty
85
+
86
+ getOutputTimestamp :: P. ModuleName -> Make. Make (Maybe UTCTime )
87
+ getOutputTimestamp _ = pure Nothing
88
+
89
+ readExterns :: P. ModuleName -> Make. Make (FilePath , Maybe P. ExternsFile )
90
+ readExterns _ = pure (" <file>" , Nothing )
91
+
92
+ codegen :: CF. Module CF. Ann -> Docs. Module -> P. ExternsFile -> P. SupplyT Make. Make ()
93
+ codegen m _ _ = do
94
+ rawJs <- J. moduleToJs m Nothing
95
+ lift $ liftIO $ IORef. writeIORef codegenRef $ Just $ P. prettyPrintJS rawJs
96
+
97
+ -- If we ever support FFI implementations in Try PureScript then we will need
98
+ -- to implement this function. However, we do not plan to support this feature.
99
+ ffiCodegen :: CF. Module CF. Ann -> Make. Make ()
100
+ ffiCodegen _ = pure ()
101
+
102
+ progress :: Make. ProgressMessage -> Make. Make ()
103
+ progress _ = pure ()
104
+
105
+ readCacheDb :: Make. Make Cache. CacheDb
106
+ readCacheDb = pure M. empty
107
+
108
+ writeCacheDb :: Cache. CacheDb -> Make. Make ()
109
+ writeCacheDb _ = pure ()
110
+
111
+ outputPrimDocs :: Make. Make ()
112
+ outputPrimDocs = pure ()
113
+
54
114
server :: [P. ExternsFile ] -> P. Env -> P. Environment -> Int -> IO ()
55
115
server externs initNamesEnv initEnv port = do
116
+ codegenRef <- IORef. newIORef Nothing
117
+ let makeActions = buildMakeActions codegenRef
56
118
let compile :: Text -> IO (Either Error ([P. JSONError ], JS ))
57
119
compile input
58
- | T. length input > 20000 = return ( Left ( OtherError " Please limit your input to 20000 characters" ))
120
+ | T. length input > 20000 = return $ Left $ OtherError " Please limit your input to 20000 characters"
59
121
| otherwise = do
60
- case CST. parseModuleFromFile " <file>" input >>= CST. resFull of
61
- Left parseError ->
62
- return . Left . CompilerErrors . P. toJSONErrors False P. Error $ CST. toMultipleErrors " <file>" parseError
63
- Right m | P. getModuleName m == P. ModuleName " Main" -> do
64
- (resultMay, ws) <- runLogger' . runExceptT . flip runReaderT P. defaultOptions $ do
65
- ((P. Module ss coms moduleName elaborated exps, env), nextVar) <- P. runSupplyT 0 $ do
66
- desugared <- P. desugar initNamesEnv externs [P. importPrim m] >>= \ case
67
- [d] -> pure d
68
- _ -> error " desugaring did not produce one module"
69
- P. runCheck' (P. emptyCheckState initEnv) $ P. typeCheckModule desugared
70
- regrouped <- P. createBindingGroups moduleName . P. collapseBindingGroups $ elaborated
71
- let mod' = P. Module ss coms moduleName regrouped exps
72
- corefn = CF. moduleToCoreFn env mod'
73
- [renamed] = P. renameInModules [corefn]
74
- unless (null . CF. moduleForeign $ renamed) . throwError . P. errorMessage $ P. MissingFFIModule moduleName
75
- P. evalSupplyT nextVar $ P. prettyPrintJS <$> J. moduleToJs renamed Nothing
76
- case resultMay of
77
- Left errs -> (return . Left . CompilerErrors . P. toJSONErrors False P. Error ) errs
78
- Right js -> (return . Right ) (P. toJSONErrors False P. Error ws, js)
79
- Right _ ->
80
- (return . Left . OtherError ) " The name of the main module should be Main."
122
+ case CST. parseModuleFromFile " <file>" input of
123
+ Left parserErrors ->
124
+ return $ Left $ toCompilerErrors parserErrors
125
+
126
+ Right partialResult -> case CST. resFull partialResult of
127
+ (_, Left parserErrors) ->
128
+ return $ Left $ toCompilerErrors parserErrors
129
+
130
+ (parserWarnings, Right m) | P. getModuleName m == P. ModuleName " Main" -> do
131
+ (makeResult, warnings) <- Make. runMake P. defaultOptions $ Make. rebuildModule makeActions [] m
132
+ codegenResult <- IORef. readIORef codegenRef
133
+ return $ case makeResult of
134
+ Left errors ->
135
+ Left $ CompilerErrors $ toJsonErrors errors
136
+ Right _ | Just js <- codegenResult -> do
137
+ let ws = warnings <> CST. toMultipleWarnings " <file>" parserWarnings
138
+ Right (toJsonErrors ws, js)
139
+ Right _ ->
140
+ Left $ OtherError " Failed to read the results of codegen."
141
+
142
+ (_, Right _) ->
143
+ return $ Left $ OtherError " The name of the main module should be Main."
81
144
82
145
scottyOpts (getOpts port) $ do
83
146
get " /" $
@@ -102,7 +165,8 @@ server externs initNamesEnv initEnv port = do
102
165
search = fst . TS. typeSearch (Just [] ) initEnv (P. emptyCheckState initEnv)
103
166
results = nubBy ((==) `on` fst ) $ do
104
167
elab <- elabs
105
- let strictMatches = search (replaceTypeVariablesAndDesugar (\ nm s -> P. Skolem P. NullSourceAnn nm s (P. SkolemScope 0 )) elab)
168
+ let mkSkolemType nm s = P. Skolem P. NullSourceAnn nm Nothing s (P. SkolemScope 0 )
169
+ strictMatches = search (replaceTypeVariablesAndDesugar mkSkolemType elab)
106
170
flexMatches = search (replaceTypeVariablesAndDesugar (const (P. TUnknown P. NullSourceAnn )) elab)
107
171
take 50 (strictMatches ++ flexMatches)
108
172
Scotty. json $ A. object [ " results" .= [ P. showQualified id k
@@ -154,7 +218,7 @@ tryParseType = hush . fmap (CST.convertType "<file>") . runParser CST.parseTypeP
154
218
155
219
runParser :: CST. Parser a -> Text -> Either String a
156
220
runParser p =
157
- first (CST. prettyPrintError . NE. head )
221
+ bimap (CST. prettyPrintError . NE. head ) snd
158
222
. CST. runTokenParser (p <* CSTM. token CST. TokEof )
159
223
. CST. lexTopLevel
160
224
0 commit comments