@@ -10,6 +10,7 @@ import System.FilePath
1010import System.IO
1111
1212import qualified Data.Binary as Binary
13+import qualified Data.List as List
1314import qualified Data.Maybe as Maybe
1415import qualified Data.Map as Map
1516import qualified Data.ByteString.Lazy as L
@@ -34,17 +35,37 @@ type Build a = BuildT IO a
3435-- Interfaces, remembering if something was recompiled
3536type BInterfaces = Map.Map String (Bool, M.ModuleInterface)
3637
37−evalBuild :: Flag.Flags -> M.Interfaces -> Build () -> IO (Maybe String)
38−evalBuild flags interfaces b = do
39− (_, s) <- evalRWST b flags (fmap notUpdated interfaces)
40− return . getLast $ s
38+evalBuild :: Flag.Flags -> M.Interfaces -> Build ()
39+ -> IO (Map.Map String M.ModuleInterface, Maybe String)
40+evalBuild flags interfaces build =
41+ do (ifaces, moduleNames) <- execRWST build flags (fmap notUpdated interfaces)
42+ return (fmap snd ifaces, getLast moduleNames)
4143 where
42− notUpdated i = (False, i)
44+ notUpdated iface = (False, iface)
4345
4446-- | Builds a list of files, returning the moduleName of the last one.
4547-- Returns \"\" if the list is empty
4648build :: Flag.Flags -> M.Interfaces -> [FilePath] -> IO String
47−build flags is = fmap (Maybe.fromMaybe "") . evalBuild flags is . buildAll
49+build flags interfaces files =
50+ do (ifaces, topName) <- evalBuild flags interfaces (buildAll files)
51+ let removeTopName = Maybe.maybe id Map.delete topName
52+ mapM_ (checkPorts topName) (Map.toList $ removeTopName ifaces)
53+ return $ Maybe.fromMaybe "" topName
54+ where
55+ checkPorts topName (name,iface)
56+ | null ports = return ()
57+ | otherwise = Print.failure msg
58+ where
59+ ports = M.iPorts iface
60+ msg = concat
61+ [ "Port Error: ports may only appear in the main module, but\n"
62+ , " sub-module ", name, " declares the following port"
63+ , if length ports == 1 then "" else "s", ": "
64+ , List.intercalate ", " ports
65+ , case topName of
66+ Nothing -> ""
67+ Just tname -> "\n All ports must appear in module " ++ tname
68+ ]
4869
4970buildAll :: [FilePath] -> Build ()
5071buildAll fs = mapM_ (uncurry build1) (zip [1..] fs)