]>
Commit | Line | Data |
---|---|---|
c194f84c | 1 | module PursLoader.Loader |
1983893b | 2 | ( Effects() |
c194f84c | 3 | , loader |
4 | , loaderFn | |
5 | ) where | |
6 | ||
2b620717 | 7 | import Prelude (Unit(), ($), (<>), (>>=), (<$>), (++), bind, flip, id, pure, return, unit, show) |
03b840cb | 8 | |
c194f84c | 9 | import Control.Monad.Aff (Aff(), runAff) |
10 | import Control.Monad.Eff (Eff()) | |
11 | import Control.Monad.Eff.Class (liftEff) | |
2b620717 | 12 | import Control.Monad.Eff.Exception (throwException, error, EXCEPTION()) |
c194f84c | 13 | |
0e1221d7 | 14 | import Data.Array ((!!), concat) |
c194f84c | 15 | import Data.Function (Fn2(), mkFn2) |
16 | import Data.Maybe (Maybe(..), fromMaybe, maybe) | |
2b620717 | 17 | import Data.Either (Either(..)) |
0e1221d7 | 18 | import Data.String (joinWith) |
2e2da2be | 19 | import Data.String.Regex (Regex(), match, noFlags, regex, test) |
07de44be | 20 | import Data.Traversable (sequence) |
2b620717 NF |
21 | import Data.Foreign (F()) |
22 | import Data.Foreign.Class (read) | |
c194f84c | 23 | |
24 | import PursLoader.ChildProcess (ChildProcess(), spawn) | |
3610dff1 | 25 | import PursLoader.FS (FS(), writeFileUtf8, findFileUtf8) |
0e1221d7 | 26 | import PursLoader.Glob (Glob(), globAll) |
3610dff1 | 27 | import PursLoader.LoaderRef (LoaderRef(), Loader(), async, cacheable, query, clearDependencies, addDependency, resourcePath) |
0e1221d7 | 28 | import PursLoader.LoaderUtil (parseQuery) |
2b620717 | 29 | import PursLoader.Options (loaderFFIOption, loaderSrcOption, pscOptions, Options(), output) |
c194f84c | 30 | |
2b620717 | 31 | type Effects eff = (cp :: ChildProcess, fs :: FS, glob :: Glob, loader :: Loader, err :: EXCEPTION | eff) |
c194f84c | 32 | |
2e2da2be | 33 | moduleRegex :: Regex |
c194f84c | 34 | moduleRegex = regex "(?:^|\\n)module\\s+([\\w\\.]+)" noFlags { ignoreCase = true } |
35 | ||
2e2da2be | 36 | foreignRegex :: Regex |
3610dff1 | 37 | foreignRegex = regex "(?:^|\\n)\\s*foreign import\\s+" noFlags { ignoreCase = true } |
38 | ||
2e2da2be | 39 | pscCommand :: String |
1983893b | 40 | pscCommand = "psc" |
c194f84c | 41 | |
2e2da2be | 42 | psciCommand :: String |
0e1221d7 | 43 | psciCommand = "psci" |
44 | ||
2e2da2be | 45 | psciFilename :: String |
0e1221d7 | 46 | psciFilename = ".psci" |
47 | ||
2e2da2be | 48 | (!!!) :: forall a. Int -> Array a -> Maybe a |
c194f84c | 49 | (!!!) = flip (!!) |
50 | ||
03b840cb | 51 | foreign import cwd :: String |
0e1221d7 | 52 | |
03b840cb | 53 | foreign import relative :: String -> String -> String |
0e1221d7 | 54 | |
07de44be | 55 | foreign import resolve :: String -> String |
56 | ||
2b620717 NF |
57 | foreign import dirname :: String -> String |
58 | ||
59 | foreign import joinPath :: String -> String -> String | |
60 | ||
03b840cb | 61 | mkPsci :: Array (Array String) -> Array (Array String) -> String |
0e1221d7 | 62 | mkPsci srcs ffis = joinWith "\n" ((loadModule <$> concat srcs) <> (loadForeign <$> concat ffis)) |
63 | where | |
64 | loadModule :: String -> String | |
65 | loadModule a = ":m " ++ relative cwd a | |
66 | ||
67 | loadForeign :: String -> String | |
68 | loadForeign a = ":f " ++ relative cwd a | |
69 | ||
03b840cb | 70 | findFFI :: forall eff. Array (Array String) -> String -> Aff (fs :: FS | eff) (Maybe String) |
3610dff1 | 71 | findFFI ffiss name = findFileUtf8 re (concat ffiss) |
72 | where | |
73 | re = regex ("(?:^|\\n)//\\s*module\\s*" ++ name ++ "\\s*\\n") noFlags | |
74 | ||
1983893b | 75 | loader' :: forall eff. LoaderRef -> String -> Aff (Effects eff) (Maybe String) |
c194f84c | 76 | loader' ref source = do |
77 | liftEff $ cacheable ref | |
78 | ||
0e1221d7 | 79 | let parsed = parseQuery $ query ref |
1983893b | 80 | srcs = fromMaybe [] (loaderSrcOption parsed) |
0e1221d7 | 81 | ffis = fromMaybe [] (loaderFFIOption parsed) |
c194f84c | 82 | |
2b620717 NF |
83 | case read parsed :: F Options of |
84 | Left e -> liftEff (throwException (error (show e))) | |
85 | Right opts -> do | |
86 | let pscOpts = pscOptions opts | |
87 | ||
88 | srcss <- globAll srcs | |
89 | ffiss <- globAll ffis | |
0e1221d7 | 90 | |
2b620717 | 91 | let psciFile = mkPsci srcss ffiss |
0e1221d7 | 92 | |
2b620717 | 93 | writeFileUtf8 psciFilename psciFile |
0e1221d7 | 94 | |
2b620717 NF |
95 | let moduleName = match moduleRegex source >>= (!!!) 1 >>= id |
96 | hasForeign = test foreignRegex source | |
97 | outputDir = resolve (output opts) | |
98 | resourceDir = dirname (resourcePath ref) | |
99 | result = (\a -> "module.exports = require('" ++ relative resourceDir (joinPath outputDir a) ++ "');") <$> moduleName | |
0e1221d7 | 100 | |
2b620717 NF |
101 | liftEff do |
102 | clearDependencies ref | |
103 | addDependency ref (resourcePath ref) | |
104 | sequence $ (\src -> addDependency ref (resolve src)) <$> concat srcss | |
3610dff1 | 105 | |
2b620717 NF |
106 | foreignPath <- if hasForeign |
107 | then fromMaybe (pure Nothing) (findFFI ffiss <$> moduleName) | |
108 | else pure Nothing | |
3610dff1 | 109 | |
2b620717 | 110 | fromMaybe (pure unit) ((\path -> liftEff (addDependency ref path)) <$> foreignPath) |
3610dff1 | 111 | |
2b620717 | 112 | spawn pscCommand (srcs <> pscOpts) |
bbd2a7af | 113 | |
2b620717 | 114 | return result |
c194f84c | 115 | |
1983893b | 116 | loader :: forall eff. LoaderRef -> String -> Eff (Effects eff) Unit |
c194f84c | 117 | loader ref source = do |
118 | callback <- async ref | |
119 | runAff (\e -> callback (Just e) "") | |
1983893b | 120 | (maybe (callback (Just (error "Loader has failed to run")) "") |
c194f84c | 121 | (callback Nothing)) |
122 | (loader' ref source) | |
123 | ||
1983893b | 124 | loaderFn :: forall eff. Fn2 LoaderRef String (Eff (Effects eff) Unit) |
c194f84c | 125 | loaderFn = mkFn2 loader |