Skip to content

Commit 7e24278

Browse files
committed
[ fix #394 ] More uniform and consistent classification of modules
1 parent 57f4365 commit 7e24278

File tree

11 files changed

+72
-44
lines changed

11 files changed

+72
-44
lines changed

src/Agda2Hs/Compile.hs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import Agda2Hs.Compile.Name ( hsTopLevelModuleName )
3030
import Agda2Hs.Compile.Postulate ( compilePostulate )
3131
import Agda2Hs.Compile.Record ( compileRecord, checkUnboxPragma )
3232
import Agda2Hs.Compile.Types
33-
import Agda2Hs.Compile.Utils ( setCurrentRangeQ, tellExtension, primModules, isPrimModule, isHsModule, isClassName )
33+
import Agda2Hs.Compile.Utils
3434
import Agda2Hs.Pragma
3535
import qualified Language.Haskell.Exts.Syntax as Hs
3636
import qualified Language.Haskell.Exts.Pretty as Hs
@@ -138,13 +138,15 @@ verifyOutput _ _ _ m ls = do
138138

139139
ensureNoOutputFromHsModules = unless (null $ concat $ map fst ls) $ do
140140
let hsModName = hsTopLevelModuleName m
141-
when (isHsModule hsModName) $ do
142-
reportSDoc "agda2hs.compile" 10 $ text "Haskell module" <+> prettyTCM m <+> text "has non-null output."
143-
genericDocError =<< hsep
144-
( pwords "The `Haskell.` namespace are reserved for binding existing Haskell modules, so the module"
145-
++ [text "`" <> prettyTCM m <> text "`"]
146-
++ pwords "should not contain any"
147-
++ [text "`{-# COMPILE AGDA2HS ... #-}`"]
148-
++ pwords "pragmas that produce Haskell code."
149-
)
150-
when (isPrimModule hsModName) __IMPOSSIBLE__
141+
case hsModuleKind hsModName of
142+
HsModule -> do
143+
reportSDoc "agda2hs.compile" 10 $ text "Haskell module" <+> prettyTCM m <+> text "has non-null output."
144+
genericDocError =<< hsep
145+
( pwords "The `Haskell.` namespace are reserved for binding existing Haskell modules, so the module"
146+
++ [text "`" <> prettyTCM m <> text "`"]
147+
++ pwords "should not contain any"
148+
++ [text "`{-# COMPILE AGDA2HS ... #-}`"]
149+
++ pwords "pragmas that produce Haskell code."
150+
)
151+
PrimModule -> __IMPOSSIBLE__
152+
AgdaModule -> return ()

src/Agda2Hs/Compile/Name.hs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,12 @@ compileQName f
109109
parent <- parentName f
110110
par <- traverse (compileName . qnameName) parent
111111
let mod0 = qnameModule $ fromMaybe f parent
112-
mod <- compileModuleName mod0
112+
(mkind, mod) <- compileModuleName mod0
113113

114114
existsInHaskell <- orM
115115
[ pure $ isJust special
116-
, pure $ isPrimModule mod
117-
, pure $ isHsModule mod
116+
, pure $ mkind == PrimModule
117+
, pure $ mkind == HsModule
118118
, hasCompilePragma f
119119
, isClassFunction f
120120
, isWhereFunction f
@@ -137,8 +137,12 @@ compileQName f
137137
Hs.Symbol _ _ -> getNamespace f
138138
Hs.Ident _ _ -> return (Hs.NoNamespace ()))
139139
let
140-
(mod', mimp) = mkImport mod qual par hf namespace
141-
qf = qualify mod' hf qual
140+
-- We don't generate "import Prelude" for primitive modules,
141+
-- unless a name is qualified.
142+
mimp = if mkind /= PrimModule || isQualified qual
143+
then Just (Import mod qual par hf namespace)
144+
else Nothing
145+
qf = qualify mod hf qual
142146

143147
-- add (possibly qualified) import
144148
whenM (asks writeImports) $
@@ -202,21 +206,6 @@ compileQName f
202206
(Pi _ absType) -> getResultType $ unAbs absType
203207
_ -> typ
204208

205-
mkImport mod qual par hf maybeIsType
206-
-- make sure the Prelude is properly qualified
207-
| isPrimModule mod
208-
= if isQualified qual then
209-
let mod' = hsModuleName "Prelude"
210-
in (mod', Just (Import mod' qual Nothing hf maybeIsType))
211-
else (mod, Nothing)
212-
| otherwise
213-
= let mod' = dropHaskellPrefix mod
214-
in (mod', Just (Import mod' qual par hf maybeIsType))
215-
216-
dropHaskellPrefix :: Hs.ModuleName () -> Hs.ModuleName ()
217-
dropHaskellPrefix (Hs.ModuleName l s) =
218-
Hs.ModuleName l $ fromMaybe s $ stripPrefix "Haskell." s
219-
220209
isWhereFunction :: QName -> C Bool
221210
isWhereFunction f = do
222211
whereMods <- asks whereModules
@@ -228,17 +217,20 @@ hsTopLevelModuleName = hsModuleName . intercalate "." . map unpack
228217

229218
-- | Given a module name (assumed to be a toplevel module),
230219
-- compute the associated Haskell module name.
231-
compileModuleName :: ModuleName -> C (Hs.ModuleName ())
220+
compileModuleName :: ModuleName -> C (HsModuleKind, Hs.ModuleName ())
232221
compileModuleName m = do
233222
tlm <- liftTCM $ hsTopLevelModuleName <$> getTopLevelModuleForModuleName m
234223
reportSDoc "agda2hs.name" 25 $
235224
text "Top-level module name for" <+> prettyTCM m <+>
236225
text "is" <+> text (pp tlm)
237-
return tlm
226+
case hsModuleKind tlm of
227+
PrimModule -> return (PrimModule, Hs.ModuleName () "Prelude")
228+
HsModule -> return (HsModule, dropHaskellPrefix tlm)
229+
AgdaModule -> return (AgdaModule, tlm)
238230

239231
importInstance :: QName -> C ()
240232
importInstance f = do
241-
mod <- compileModuleName $ qnameModule f
242-
unless (isPrimModule mod) $ do
233+
(kind, mod) <- compileModuleName $ qnameModule f
234+
unless (kind == PrimModule) $ do
243235
reportSLn "agda2hs.import" 20 $ "Importing instances from " ++ pp mod
244236
tellImport $ ImportInstances mod

src/Agda2Hs/Compile/Utils.hs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import Control.Monad.Reader
77
import Control.Monad.Writer ( tell )
88
import Control.Monad.State ( put, modify )
99

10-
import Data.List ( isPrefixOf )
10+
import Data.List ( isPrefixOf, stripPrefix )
1111
import Data.Maybe ( isJust )
1212
import qualified Data.Map as M
13-
import Data.List ( isPrefixOf )
1413

1514
import qualified Language.Haskell.Exts as Hs
1615

@@ -51,6 +50,11 @@ import Agda2Hs.Pragma
5150
import qualified Data.List as L
5251
import Agda.Utils.Impossible ( __IMPOSSIBLE__ )
5352

53+
data HsModuleKind
54+
= PrimModule
55+
| HsModule
56+
| AgdaModule
57+
deriving (Eq)
5458

5559
-- | Primitive modules provided by the agda2hs library.
5660
-- None of those (and none of their children) will get processed.
@@ -61,11 +65,15 @@ primModules =
6165
, "Haskell.Prelude"
6266
]
6367

64-
isPrimModule :: Hs.ModuleName () -> Bool
65-
isPrimModule mod = any (`isPrefixOf` pp mod) primModules
68+
hsModuleKind :: Hs.ModuleName () -> HsModuleKind
69+
hsModuleKind mod
70+
| any (`isPrefixOf` pp mod) primModules = PrimModule
71+
| "Haskell." `isPrefixOf` pp mod = HsModule
72+
| otherwise = AgdaModule
6673

67-
isHsModule :: Hs.ModuleName () -> Bool
68-
isHsModule mod = "Haskell." `isPrefixOf` pp mod
74+
dropHaskellPrefix :: Hs.ModuleName () -> Hs.ModuleName ()
75+
dropHaskellPrefix (Hs.ModuleName l s) =
76+
Hs.ModuleName l $ fromMaybe s $ stripPrefix "Haskell." s
6977

7078
concatUnzip :: [([a], [b])] -> ([a], [b])
7179
concatUnzip = (concat *** concat) . unzip

test/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
build/
22
agda2hs
3-
Haskell/
43
html/

test/AllTests.agda

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ import Issue308
9595
import Issue324
9696
import Assert
9797
import Issue377
98+
import Issue394
9899

99100
{-# FOREIGN AGDA2HS
100101
import Issue14
@@ -187,4 +188,5 @@ import Issue308
187188
import Issue324
188189
import Assert
189190
import Issue377
191+
import Issue394
190192
#-}

test/Haskell/Data/ByteString.agda

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module Haskell.Data.ByteString where
2+
3+
open import Haskell.Prelude
4+
5+
postulate
6+
ByteString : Set
7+
8+
instance
9+
iEqByteString : Eq ByteString

test/Issue394.agda

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
open import Haskell.Prelude
3+
open import Haskell.Data.ByteString using (ByteString)
4+
5+
test : ByteString ByteString Bool
6+
test x y = x == y
7+
8+
{-# COMPILE AGDA2HS test #-}

test/golden/AllTests.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,5 @@ import Issue308
9090
import Issue324
9191
import Assert
9292
import Issue377
93+
import Issue394
9394

test/golden/CommonQualifiedImports.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module CommonQualifiedImports where
22

33
import qualified Importee as Common (foo)
4-
import qualified Prelude as Common (Int, (+))
4+
import qualified Prelude as Common (Int, Num((+)))
55
import qualified SecondImportee as Common (anotherFoo)
66

77
-- ** common qualification

test/golden/Issue394.hs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Issue394 where
2+
3+
import Data.ByteString (ByteString)
4+
5+
test :: ByteString -> ByteString -> Bool
6+
test x y = x == y
7+

test/golden/QualifiedPrelude.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module QualifiedPrelude where
22

33
import Numeric.Natural (Natural)
4-
import qualified Prelude as Pre (foldr, (+), (.))
4+
import qualified Prelude as Pre (Foldable(foldr), Num((+)), (.))
55

66
-- ** qualifying the Prelude
77

0 commit comments

Comments
 (0)