diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-02-17 11:21:35 +0100 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-02-17 11:21:35 +0100 |
commit | ed7cff18118bddc2b57fe1738e7edb2fb0064305 (patch) | |
tree | ac38ae6e0e66103429a779c86ce36fc30ea465b3 /src/LambdaCube | |
parent | 02d18fe787cbe69d422ad9f76a5324f6ba86f4da (diff) |
better path handling
Diffstat (limited to 'src/LambdaCube')
-rw-r--r-- | src/LambdaCube/Compiler.hs | 53 |
1 files changed, 25 insertions, 28 deletions
diff --git a/src/LambdaCube/Compiler.hs b/src/LambdaCube/Compiler.hs index 5f7bd4fd..fc9068cc 100644 --- a/src/LambdaCube/Compiler.hs +++ b/src/LambdaCube/Compiler.hs | |||
@@ -24,8 +24,8 @@ module LambdaCube.Compiler | |||
24 | , prettyShowUnlines | 24 | , prettyShowUnlines |
25 | ) where | 25 | ) where |
26 | 26 | ||
27 | import Data.Char | ||
28 | import Data.List | 27 | import Data.List |
28 | import Data.Function | ||
29 | import Data.Map.Strict (Map) | 29 | import Data.Map.Strict (Map) |
30 | import qualified Data.Map.Strict as Map | 30 | import qualified Data.Map.Strict as Map |
31 | import Control.Monad.State | 31 | import Control.Monad.State |
@@ -39,7 +39,6 @@ import Control.Exception hiding (catch, bracket, finally, mask) | |||
39 | import Control.Arrow hiding ((<+>)) | 39 | import Control.Arrow hiding ((<+>)) |
40 | import System.Directory | 40 | import System.Directory |
41 | import System.FilePath | 41 | import System.FilePath |
42 | --import Debug.Trace | ||
43 | import qualified Data.Text as T | 42 | import qualified Data.Text as T |
44 | import qualified Data.Text.IO as TIO | 43 | import qualified Data.Text.IO as TIO |
45 | import qualified Text.Show.Pretty as PP | 44 | import qualified Text.Show.Pretty as PP |
@@ -59,7 +58,7 @@ type EName = String | |||
59 | type MName = String | 58 | type MName = String |
60 | 59 | ||
61 | type Modules = Map FilePath (Either Doc (PolyEnv, String)) | 60 | type Modules = Map FilePath (Either Doc (PolyEnv, String)) |
62 | type ModuleFetcher m = Maybe FilePath -> MName -> m (FilePath, String) | 61 | type ModuleFetcher m = Maybe FilePath -> MName -> m (FilePath, MName, String) |
63 | 62 | ||
64 | -- todo: use RWS | 63 | -- todo: use RWS |
65 | newtype MMT m a = MMT { runMMT :: ExceptT String (ReaderT (ModuleFetcher (MMT m)) (StateT Modules (WriterT Infos m))) a } | 64 | newtype MMT m a = MMT { runMMT :: ExceptT String (ReaderT (ModuleFetcher (MMT m)) (StateT Modules (WriterT Infos m))) a } |
@@ -94,7 +93,7 @@ catchMM m e = mapMMT (lift . mapReaderT (mapStateT $ lift . runWriterT >=> f) . | |||
94 | f ((Right x, m), is) = tell is >> return (Right x, m) | 93 | f ((Right x, m), is) = tell is >> return (Right x, m) |
95 | f ((Left e, m), is) = return (Left (e, is), m) | 94 | f ((Left e, m), is) = return (Left (e, is), m) |
96 | 95 | ||
97 | -- TODO: remove dependent modules from cache too | 96 | -- TODO: remove dependent modules from cache too? |
98 | removeFromCache :: Monad m => FilePath -> MMT m () | 97 | removeFromCache :: Monad m => FilePath -> MMT m () |
99 | removeFromCache f = modify $ Map.delete f | 98 | removeFromCache f = modify $ Map.delete f |
100 | 99 | ||
@@ -110,34 +109,32 @@ ioFetch :: MonadIO m => [FilePath] -> ModuleFetcher (MMT m) | |||
110 | ioFetch paths imp n = do | 109 | ioFetch paths imp n = do |
111 | preludePath <- (</> "lc") <$> liftIO getDataDir | 110 | preludePath <- (</> "lc") <$> liftIO getDataDir |
112 | let | 111 | let |
113 | f [] = throwError $ show $ "can't find module" <+> hsep (map text fnames) | 112 | fnames = nubBy ((==) `on` fst) $ map (first normalise) $ concatMap lcModuleFile $ paths ++ [preludePath] |
114 | f (x:xs) = liftIO (readFile' x) >>= \case | 113 | lcModuleFile path = g imp |
115 | Nothing -> f xs | ||
116 | Just src -> do | ||
117 | --liftIO $ putStrLn $ "loading " ++ x | ||
118 | return (x, src) | ||
119 | fnames = map normalise . concatMap lcModuleFile $ nub $ preludePath : paths | ||
120 | lcModuleFile path = (++ ".lc") <$> g imp | ||
121 | where | 114 | where |
122 | g Nothing = [path </> n] | 115 | g _ | takeExtension n == ".lc" = [(path </> n, intercalate "." $ remDot $ (\(a, b) -> a ++ [b]) $ map takeDirectory . splitPath *** id $ splitFileName $ dropExtension $ normalise n)] |
123 | g (Just fn) = [path </> hn, fst (splitMPath fn) </> hn] | 116 | | otherwise = [(path </> hn n ++ ".lc", n)] |
124 | 117 | ||
125 | hn = h [] n | 118 | remDot (".": xs) = xs |
119 | remDot xs = xs | ||
120 | |||
121 | hn = h [] | ||
126 | h acc [] = reverse acc | 122 | h acc [] = reverse acc |
127 | h acc ('.':cs) = reverse acc </> h [] cs | 123 | h acc ('.':cs) = reverse acc </> hn cs |
128 | h acc (c: cs) = h (c: acc) cs | 124 | h acc (c: cs) = h (c: acc) cs |
129 | f fnames | ||
130 | |||
131 | splitMPath fn = (joinPath as, intercalate "." $ bs ++ [y]) | ||
132 | where | ||
133 | (as, bs) = span (\x -> null x || not (isUpper $ head x)) xs | ||
134 | (xs, y) = map takeDirectory . splitPath *** id $ splitFileName $ dropExtension fn | ||
135 | 125 | ||
126 | f [] = throwError $ show $ "can't find module" <+> text n <+> "in path" <+> hsep (map text paths) | ||
127 | f ((x, mn): xs) = liftIO (readFile' x) >>= \case | ||
128 | Nothing -> f xs | ||
129 | Just src -> do | ||
130 | --liftIO $ putStrLn $ "loading " ++ x | ||
131 | return (x, mn, src) | ||
132 | f fnames | ||
136 | 133 | ||
137 | loadModule :: MonadMask m => Maybe FilePath -> MName -> MMT m (FilePath, PolyEnv) | 134 | loadModule :: MonadMask m => Maybe FilePath -> MName -> MMT m (FilePath, PolyEnv) |
138 | loadModule imp mname = do | 135 | loadModule imp mname_ = do |
139 | fetch <- ask | 136 | fetch <- ask |
140 | (fname, src) <- fetch imp mname | 137 | (fname, mname, src) <- fetch imp mname_ |
141 | c <- gets $ Map.lookup fname | 138 | c <- gets $ Map.lookup fname |
142 | case c of | 139 | case c of |
143 | Just (Right (m, _)) -> return (fname, m) | 140 | Just (Right (m, _)) -> return (fname, m) |
@@ -161,11 +158,11 @@ loadModule imp mname = do | |||
161 | ExportId (snd -> d) -> case Map.lookup d $ getPolyEnv x of | 158 | ExportId (snd -> d) -> case Map.lookup d $ getPolyEnv x of |
162 | Just def -> PolyEnv (Map.singleton d def) mempty | 159 | Just def -> PolyEnv (Map.singleton d def) mempty |
163 | Nothing -> error $ d ++ " is not defined" | 160 | Nothing -> error $ d ++ " is not defined" |
164 | ExportModule (snd -> m) | m == snd (splitMPath fname) -> x | 161 | ExportModule (snd -> m) | m == mname -> x |
165 | ExportModule m -> case [ ms | 162 | ExportModule m -> case [ ms |
166 | | ((m', is), ms) <- zip (moduleImports e) ms, m' == m] of | 163 | | ((m', is), ms) <- zip (moduleImports e) ms, m' == m] of |
167 | [PolyEnv x infos] -> PolyEnv x mempty -- TODO | 164 | [PolyEnv x infos] -> PolyEnv x mempty -- TODO |
168 | [] -> error $ "empty export list: " ++ show (fname, m, map fst $ moduleImports e, snd (splitMPath fname)) | 165 | [] -> error $ "empty export list: " ++ show (fname, m, map fst $ moduleImports e, mname) |
169 | _ -> error "export list: internal error" | 166 | _ -> error "export list: internal error" |
170 | modify $ Map.insert fname $ Right (x', src) | 167 | modify $ Map.insert fname $ Right (x', src) |
171 | return (fname, x') | 168 | return (fname, x') |
@@ -211,8 +208,8 @@ preCompile paths paths' backend mod = do | |||
211 | first (compilePipeline backend) <$> parseAndToCoreMain "Main" | 208 | first (compilePipeline backend) <$> parseAndToCoreMain "Main" |
212 | where | 209 | where |
213 | fetch imp = \case | 210 | fetch imp = \case |
214 | "Prelude" -> return ("./Prelude.lc", undefined) | 211 | "Prelude" -> return ("./Prelude.lc", "Prelude", undefined) |
215 | "Main" -> return ("./Main.lc", src) | 212 | "Main" -> return ("./Main.lc", "Main", src) |
216 | n -> ioFetch paths' imp n | 213 | n -> ioFetch paths' imp n |
217 | 214 | ||
218 | prettyShowUnlines :: Show a => a -> String | 215 | prettyShowUnlines :: Show a => a -> String |