1- {-# LANGUAGE NamedFieldPuns #-}
1+ {-# LANGUAGE NamedFieldPuns, ImportQualifiedPost #-}
22-- | Convert Agda datatypes to λ□ inductive declarations
33module Agda2Lambox.Convert.Data
44 ( convertDatatype
55 ) where
66
77import Control.Monad.Reader ( ask , liftIO )
8- import Control.Monad ( forM , when , unless )
8+ import Control.Monad ( forM , when , unless , (>=>) )
9+ import Data.Traversable ( mapM )
10+ import Data.Foldable ( toList )
911import Data.List ( elemIndex )
1012import Data.Maybe ( isJust )
1113
@@ -17,9 +19,9 @@ import Agda.Utils
1719import Agda.Syntax.Abstract.Name ( qnameModule , qnameName )
1820import Agda.TypeChecking.Monad.Base
1921import Agda.TypeChecking.Monad.Env ( withCurrentModule )
20- import Agda.TypeChecking.Datatypes ( ConstructorInfo (.. ), getConstructorInfo )
22+ import Agda.TypeChecking.Datatypes ( ConstructorInfo (.. ), getConstructorInfo , isDatatype )
2123import Agda.Compiler.ToTreeless ( toTreeless )
22- import Agda.Compiler.Backend ( getConstInfo )
24+ import Agda.Compiler.Backend ( getConstInfo , lookupMutualBlock )
2325import Agda.Syntax.Treeless ( EvaluationStrategy (EagerEvaluation ) )
2426import Agda.Syntax.Common.Pretty ( prettyShow )
2527
@@ -30,16 +32,46 @@ import Agda2Lambox.Convert.Class
3032import Agda.Utils.Monad (guardWithError )
3133
3234
33- -- | Convert a datatype definition to a Lambdabox declaration.
34- convertDatatype :: Definition :~> GlobalDecl
35- convertDatatype defn@ Defn {defName, theDef, defMutual} =
36- withCurrentModule (qnameModule defName) do
37- let Datatype {.. } = theDef
35+ -- | Toplevel conversion from a datatype definition to a Lambdabox declaration.
36+ convertDatatype :: Definition :~> Maybe GlobalDecl
37+ convertDatatype defn@ Defn {defName, defMutual} = do
38+ -- we lookup names in the mutual block
39+ MutualBlock {mutualNames} <- lookupMutualBlock defMutual
40+
41+ let names = toList mutualNames
42+
43+ -- we consider that the *lowest name* in the mutual block
44+ -- is the *representative* of the mutual block
45+ -- i.e that's when we trigger the compilation of the mutual block
46+
47+ if defName /= head names then return Nothing
48+ else do
49+
50+ -- when it's time to compile the mutual block
51+ -- we make sure that all definitions in the block are datatypes (for now)
52+
53+ onlyDatas :: Bool <- and <$> mapM (liftTCM . isDatatype) names
54+
55+ unless onlyDatas $ fail " not supported: mutual datatypes with non-datatypes"
56+
57+ bodies <- forM names $ liftTCM . getConstInfo >=> actuallyConvertDatatype
58+
59+ return $ Just $ InductiveDecl $ MutualInductive
60+ { indFinite = Finite
61+ -- NOTE(flupe): Agda's datatypes are *always* finite?
62+ -- Co-induction is restricted to records.
63+ -- We may want to set BiFinite for non-recursive datatypes, but I don't know yet.
64+ -- in anycase, once we also accept coinductive records in the mix, probably we should pick CoFinite
65+ , indPars = 0
66+ , indBodies = bodies
67+ }
3868
39- let Just muts = dataMutual
4069
41- unless (length muts < 2 ) $
42- fail $ " mututal datatypes not supported" <> prettyShow dataMutual
70+
71+ actuallyConvertDatatype :: Definition :~> OneInductiveBody
72+ actuallyConvertDatatype defn@ Defn {defName, theDef, defMutual} =
73+ withCurrentModule (qnameModule defName) do
74+ let Datatype {.. } = theDef
4375
4476 ctors :: [ConstructorBody ]
4577 <- forM dataCons \ cname -> do
@@ -49,22 +81,14 @@ convertDatatype defn@Defn{defName, theDef, defMutual} =
4981 , ctorArgs = arity
5082 }
5183
52- let
53- inductive = OneInductive
54- { indName = prettyShow $ qnameName defName
55- , indPropositional = False
56- -- TODO(flupe): ^ take care of this (use datatypeSort to figure this out)
57- , indKElim = IntoAny
58- -- TODO(flupe): also take care of this (with the Sort)
59- , indCtors = ctors
60- , indProjs = []
61- }
62-
63- return $ InductiveDecl $ MutualInductive
64- { indFinite = Finite
65- -- NOTE(flupe): Agda's datatypes are *always* finite?
66- -- Co-induction is restricted to records.
67- -- We may want to set BiFinite for non-recursive datatypes, but I don't know yet.
68- , indPars = 0
69- , indBodies = [inductive]
84+ return OneInductive
85+ { indName = prettyShow $ qnameName defName
86+ , indPropositional = False
87+ -- TODO(flupe): ^ take care of this (use datatypeSort to figure this out)
88+ , indKElim = IntoAny
89+ -- TODO(flupe): also take care of this (with the Sort)
90+ , indCtors = ctors
91+ , indProjs = []
7092 }
93+
94+
0 commit comments