processExternalImports :: L2.L2NamespaceID -> ModelTranslation ()
processExternalImports ns = do
  ModelTranslationState { mtsL2Model = m, mtsL2ToL1Map = nsmap } <- get
  let Just (L1.L1NamespaceContents nsc) = M.lookup ns nsmap
  forM_ nsc $ \st -> case st of
    L1.L1NSImport { L1.l1nsSS = ss,
                    L1.l1nsImportFrom = Just from,
                    L1.l1nsImportPath = path,
                    L1.l1nsImportWhat = what,
                    L1.l1nsImportHiding = hiding } -> do
      -- Find the model we are importing from...
      (_, _, impMap) <- ask
      impMod <-
           maybe (fail $ "Reference to imported model " ++ (BSC.unpack from) ++ " at " ++
                  (show ss) ++ ", but that model does not appear to have been loaded successfully.")
                 return
                 (M.lookup from impMap)
      let L1.L1RelOrAbsPath pathSS isAbs rpath = path
      when (not isAbs) . fail $ "Import at " ++ (show pathSS) ++
           " uses both a from clause and a relative path, which is invalid."
      impNS <- findNamespaceInL2UsingL1Path nsMain impMod rpath
      symList <- importListFromWhatAndHiding impNS impMod what hiding
      mapM_ (recursivelyImportExternalSymbol impMod from impNS ns) symList
    L1.L1NSNamespace { L1.l1nsNamespaceName = L1.L1Identifier _ nsid, L1.l1nsNamespaceContents = nsc} -> do
      Just childNSID <- findExactNamespace ns nsid
      processExternalImports childNSID
    L1.L1NSDomain { L1.l1nsDomainName = L1.L1Identifier _ nsid, L1.l1nsNamespaceContents = nsc} -> do
      Just childNSID <- findExactNamespace ns nsid
      processExternalImports childNSID
    _ -> return ()

-- | Pulls in a symbol from another model, along with everything needed for that
--  symbol to be used.
processExternalImports :: L2.L2NamespaceID -> ModelTranslation ()
processExternalImports ns = do
  ModelTranslationState { mtsL2Model = m, mtsL2ToL1Map = nsmap } <- get
  let Just (L1.L1NamespaceContents nsc) = M.lookup ns nsmap
  forM_ nsc $ \st -> case st of
    L1.L1NSImport { L1.l1nsSS = ss,
                    L1.l1nsImportFrom = Just from,
                    L1.l1nsImportPath = path,
                    L1.l1nsImportWhat = what,
                    L1.l1nsImportHiding = hiding } -> do
      -- Find the model we are importing from...
      (_, _, impMap) <- ask
      impMod <-
           maybe (fail $ "Reference to imported model " ++ (BSC.unpack from) ++ " at " ++
                  (show ss) ++ ", but that model does not appear to have been loaded successfully.")
                 return
                 (M.lookup from impMap)
      let L1.L1RelOrAbsPath pathSS isAbs rpath = path
      when (not isAbs) . fail $ "Import at " ++ (show pathSS) ++
           " uses both a from clause and a relative path, which is invalid."
      impNS <- findNamespaceInL2UsingL1Path nsMain impMod rpath
      symList <- importListFromWhatAndHiding impNS impMod what hiding
      mapM_ (recursivelyImportExternalSymbol impMod from impNS ns) symList
    L1.L1NSNamespace { L1.l1nsNamespaceName = L1.L1Identifier _ nsid, L1.l1nsNamespaceContents = nsc} -> do
      Just childNSID <- findExactNamespace ns nsid
      processExternalImports childNSID
    L1.L1NSDomain { L1.l1nsDomainName = L1.L1Identifier _ nsid, L1.l1nsNamespaceContents = nsc} -> do
      Just childNSID <- findExactNamespace ns nsid
      processExternalImports childNSID
    _ -> return ()

-- | Pulls in a symbol from another model, along with everything needed for that
--  symbol to be used.
processExternalImports ns = do
  ModelTranslationState { mtsL2Model = m, mtsL2ToL1Map = nsmap } <- get
  let Just (L1.L1NamespaceContents nsc) = M.lookup ns nsmap
  forM_ nsc $ \st -> case st of
    L1.L1NSImport { L1.l1nsSS = ss,
                    L1.l1nsImportFrom = Just from,
                    L1.l1nsImportPath = path,
                    L1.l1nsImportWhat = what,
                    L1.l1nsImportHiding = hiding } -> do
      -- Find the model we are importing from...
      (_, _, impMap) <- ask
      impMod <-
           maybe (fail $ "Reference to imported model " ++ (BSC.unpack from) ++ " at " ++
                  (show ss) ++ ", but that model does not appear to have been loaded successfully.")
                 return
                 (M.lookup from impMap)
      let L1.L1RelOrAbsPath pathSS isAbs rpath = path
      when (not isAbs) . fail $ "Import at " ++ (show pathSS) ++
           " uses both a from clause and a relative path, which is invalid."
      impNS <- findNamespaceInL2UsingL1Path nsMain impMod rpath
      symList <- importListFromWhatAndHiding impNS impMod what hiding
      mapM_ (recursivelyImportExternalSymbol impMod from impNS ns) symList
    L1.L1NSNamespace { L1.l1nsNamespaceName = L1.L1Identifier _ nsid, L1.l1nsNamespaceContents = nsc} -> do
      Just childNSID <- findExactNamespace ns nsid
      processExternalImports childNSID
    L1.L1NSDomain { L1.l1nsDomainName = L1.L1Identifier _ nsid, L1.l1nsNamespaceContents = nsc} -> do
      Just childNSID <- findExactNamespace ns nsid
      processExternalImports childNSID
    _ -> return ()

-- | Pulls in a symbol from another model, along with everything needed for that
--  symbol to be used.