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