Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add error for overloaded Haskell constructors #328

Merged
merged 4 commits into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions src/Agda2Hs/Compile.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Control.Monad.Trans.RWS.CPS ( evalRWST )
import Control.Monad.State ( gets )
import Control.Arrow ((>>>))
import Data.Functor
import Data.List ( isPrefixOf )
import Data.List ( isPrefixOf, group, sort )

import qualified Data.Map as M

Expand All @@ -15,7 +15,7 @@ import Agda.Syntax.Common.Pretty ( prettyShow )
import Agda.TypeChecking.Pretty
import Agda.TypeChecking.Monad.Signature ( isInlineFun )
import Agda.Utils.Null
import Agda.Utils.Monad ( whenM, anyM )
import Agda.Utils.Monad ( whenM, anyM, when )

import qualified Language.Haskell.Exts.Extension as Hs

Expand All @@ -27,6 +27,8 @@ import Agda2Hs.Compile.Record ( compileRecord, checkUnboxPragma )
import Agda2Hs.Compile.Types
import Agda2Hs.Compile.Utils ( setCurrentRangeQ, tellExtension, primModules, isClassName )
import Agda2Hs.Pragma
import qualified Language.Haskell.Exts.Syntax as Hs
import qualified Language.Haskell.Exts.Pretty as Hs


initCompileEnv :: TopLevelModuleName -> SpecialRules -> CompileEnv
Expand Down Expand Up @@ -54,12 +56,11 @@ moduleSetup _ _ m _ = do
setScope . iInsideScope =<< curIF
return $ Recompile m


-- Main compile function
------------------------

compile
:: Options -> ModuleEnv -> IsMain -> Definition
:: Options -> ModuleEnv -> IsMain -> Definition
-> TCM (CompiledDef, CompileOutput)
compile opts tlm _ def =
withCurrentModule (qnameModule qname)
Expand All @@ -80,7 +81,7 @@ compile opts tlm _ def =
reportSDoc "agda2hs.compile" 45 $ text "Pragma:" <+> text (show p)
reportSDoc "agda2hs.compile" 45 $ text "Compiling definition:" <+> pretty (theDef def)

isInstance <- anyM (defInstance def) isClassName
isInstance <- anyM (defInstance def) isClassName

reportSDoc "agda2hs.compile" 15 $ text "Is instance?" <+> prettyTCM isInstance

Expand All @@ -106,3 +107,25 @@ compile opts tlm _ def =

postCompile :: C ()
postCompile = whenM (gets $ lcaseUsed >>> (> 0)) $ tellExtension Hs.LambdaCase

verifyOutput ::
Options -> ModuleEnv -> IsMain -> TopLevelModuleName
-> [(CompiledDef, CompileOutput)] -> TCM Bool
verifyOutput _ _ _ m ls = do
reportSDoc "agda2hs.compile" 5 $ text "Checking generated output before rendering: " <+> prettyTCM m
ensureUniqueConstructors
where
ensureUniqueConstructors = do
let allCons = do
(r, _) <- ls
(_, a) <- r
Hs.DataDecl _ _ _ _ cons _ <- a
Hs.QualConDecl _ _ _ con <- cons
return $ case con of
Hs.ConDecl _ n _ -> n
Hs.InfixConDecl _ _ n _ -> n
Hs.RecDecl _ n _ -> n
duplicateCons = filter ((> 1) . length) . group . sort $ allCons
when (length duplicateCons > 0) $
genericDocError =<< vcat (map (\x -> text $ "Cannot generate multiple constructors with the same identifier: " <> Hs.prettyPrint (head x)) duplicateCons)
return (length duplicateCons == 0)
4 changes: 3 additions & 1 deletion src/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ backend = Backend'
, preCompile = checkConfig
, postCompile = \ _ _ _ -> return ()
, preModule = moduleSetup
, postModule = writeModule
, postModule = verifyAndWriteModule
, compileDef = compile
, scopeCheckingSuffices = False
, mayEraseType = \ _ -> return True
}
where
verifyAndWriteModule opts env isM m out = verifyOutput opts env isM m out >> writeModule opts env isM m out

-- | Parse command-line arguments to check whether we are in interactive mode.
isInteractive :: IO Bool
Expand Down
16 changes: 16 additions & 0 deletions test/Fail/Issue125.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module Fail.Issue125 where

data A (a : Set) : Set where
ACtr : a -> A a

{-# COMPILE AGDA2HS A #-}

data B : Set where
ACtr : B

{-# COMPILE AGDA2HS B #-}

data C : Set where
Ca : C

{-# COMPILE AGDA2HS C #-}
1 change: 1 addition & 0 deletions test/golden/Issue125.err
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cannot generate multiple constructors with the same identifier: ACtr
Loading