1+ {-# OPTIONS_GHC -Wno-redundant-constraints #-}
2+
13module LambdaBuffers.Compiler.KindCheck (
24 -- * Kindchecking functions.
35 check ,
@@ -11,9 +13,10 @@ module LambdaBuffers.Compiler.KindCheck (
1113
1214import Control.Lens (view , (&) , (.~) , (^.) )
1315import Control.Monad (void )
14- import Control.Monad.Freer (Eff , Members , reinterpret , run )
16+ import Control.Monad.Freer (Eff , Member , Members , interpret , reinterpret , run )
1517import Control.Monad.Freer.Error (Error , runError , throwError )
1618import Control.Monad.Freer.Reader (Reader , ask , runReader )
19+ import Control.Monad.Freer.State (State , evalState , get , modify )
1720import Control.Monad.Freer.TH (makeEffect )
1821import Data.Foldable (traverse_ )
1922import Data.List.NonEmpty (NonEmpty ((:|) ), uncons , (<|) )
@@ -36,51 +39,12 @@ import LambdaBuffers.Compiler.KindCheck.Inference qualified as I
3639import LambdaBuffers.Compiler.KindCheck.Type (Type (App ))
3740import LambdaBuffers.Compiler.KindCheck.Variable (Variable (ForeignRef , LocalRef ))
3841import LambdaBuffers.Compiler.ProtoCompat (kind2ProtoKind )
39- import LambdaBuffers.Compiler.ProtoCompat.Types qualified as P (
40- ClassDef ,
41- CompilerError (.. ),
42- CompilerInput ,
43- Constructor ,
44- Field ,
45- ForeignRef ,
46- InstanceClause ,
47- Kind ,
48- KindCheckError (
49- InconsistentTypeError ,
50- IncorrectApplicationError ,
51- RecursiveKindError ,
52- UnboundTermError
53- ),
54- KindRefType (KType ),
55- KindType (KindArrow , KindRef ),
56- LocalRef ,
57- Module ,
58- ModuleName ,
59- Product (.. ),
60- Record ,
61- SourceInfo (SourceInfo ),
62- SourcePosition (SourcePosition ),
63- Sum ,
64- Tuple ,
65- Ty (.. ),
66- TyAbs ,
67- TyApp ,
68- TyArg ,
69- TyBody (.. ),
70- TyDef (TyDef ),
71- TyName ,
72- TyRef (.. ),
73- TyVar ,
74- VarName (VarName ),
75- )
42+ import LambdaBuffers.Compiler.ProtoCompat.Types qualified as P
7643import LambdaBuffers.Compiler.ProtoCompat.Types qualified as PT
7744
7845--------------------------------------------------------------------------------
7946-- Types
8047
81- -- FIXME(cstml) - We should add the following tests:
82- -- - double declaration of a type
83-
8448-- | Kind Check failure types.
8549type CompilerErr = P. CompilerError
8650
@@ -121,20 +85,27 @@ makeEffect ''KindCheck
12185
12286--------------------------------------------------------------------------------
12387
124- runCheck :: Eff (Check ': '[] ) a -> Either CompilerErr a
88+ -- | The Check effect runner.
89+ runCheck :: Eff '[Check , Err ] a -> Either CompilerErr a
12590runCheck = run . runError . runKindCheck . localStrategy . moduleStrategy . globalStrategy
12691
127- -- | Run the check - return the validated context or the failure.
92+ {- | Run the check - return the validated context or the failure. The main API
93+ function of the library.
94+ -}
12895check :: P. CompilerInput -> PT. CompilerOutput
12996check = fmap (const PT. CompilerResult ) . runCheck . kCheck
13097
131- -- | Run the check - drop the result if it succeeds.
98+ -- | Run the check - drop the result if it succeeds - useful for testing .
13299check_ :: P. CompilerInput -> Either CompilerErr ()
133100check_ = void . runCheck . kCheck
134101
135102--------------------------------------------------------------------------------
136103
137- type Transform x y = forall effs {a }. Eff (x ': effs ) a -> Eff (y ': effs ) a
104+ {- | A transformation (in the context of the Kind Checker) is a mapping from one
105+ Effect to another. All effects can fial via the `Err` effect - which is
106+ essentially the Kind Check failure.
107+ -}
108+ type Transform x y = forall effs {a }. Member Err effs = > Eff (x ': effs ) a -> Eff (y ': effs ) a
138109
139110-- Transformation strategies
140111globalStrategy :: Transform Check GlobalCheck
@@ -146,7 +117,7 @@ globalStrategy = reinterpret $ \case
146117
147118moduleStrategy :: Transform GlobalCheck ModuleCheck
148119moduleStrategy = reinterpret $ \ case
149- CreateContext ci -> resolveCreateContext ci
120+ CreateContext ci -> evalState ( mempty @ ( M. Map Variable P. TyDef )) . resolveCreateContext $ ci
150121 ValidateModule cx md -> do
151122 traverse_ (kCTypeDefinition (module2ModuleName md) cx) (md ^. # typeDefs)
152123 traverse_ (kCClassInstance cx) (md ^. # instances)
@@ -159,14 +130,14 @@ localStrategy = reinterpret $ \case
159130 KCClassInstance _ctx _instClause -> pure () -- "FIXME(cstml)"
160131 KCClass _ctx _classDef -> pure () -- "FIXME(cstml)"
161132
162- runKindCheck :: Eff '[ KindCheck ] a -> Eff '[ Err ] a
163- runKindCheck = reinterpret $ \ case
133+ runKindCheck :: forall effs { a } . Member Err effs => Eff ( KindCheck ' : effs ) a -> Eff effs a
134+ runKindCheck = interpret $ \ case
164135 KindFromTyDef moduleName tydef -> runReader moduleName (tyDef2Type tydef)
165136 -- TyDefToTypes moduleName tydef -> runReader moduleName (tyDef2Types tydef)
166137 InferTypeKind _modName tyDef ctx ty -> either (handleErr tyDef) pure $ infer ctx ty
167138 CheckKindConsistency mname def ctx k -> runReader mname $ resolveKindConsistency def ctx k
168139 where
169- handleErr :: forall a . P. TyDef -> InferErr -> Eff '[ Err ] a
140+ handleErr :: forall { b } . P. TyDef -> InferErr -> Eff effs b
170141 handleErr td = \ case
171142 InferUnboundTermErr uA ->
172143 throwError . P. CompKindCheckError $ P. UnboundTermError (tyDef2TyName td) (var2VarName uA)
@@ -208,15 +179,65 @@ resolveKindConsistency tydef _ctx inferredKind = do
208179 throwError . P. CompKindCheckError $
209180 P. InconsistentTypeError n (kind2ProtoKind i) (kind2ProtoKind d)
210181
211- resolveCreateContext :: forall effs . P. CompilerInput -> Eff effs Context
212- resolveCreateContext ci = mconcat <$> traverse module2Context (ci ^. # modules)
213-
214182tyDef2TyName :: P. TyDef -> P. TyName
215183tyDef2TyName (P. TyDef n _ _) = n
216184
217- module2Context :: forall effs . P. Module -> Eff effs Context
218- module2Context m = mconcat <$> traverse (tyDef2Context (moduleName2ModName (m ^. # moduleName))) (m ^. # typeDefs)
185+ --------------------------------------------------------------------------------
186+ -- Context Creation
219187
188+ {- | Resolver function for the context creation - it fails if two identical
189+ declarations are found.
190+ -}
191+ resolveCreateContext ::
192+ forall effs .
193+ Member (State (M. Map Variable P. TyDef )) effs =>
194+ Member Err effs =>
195+ P. CompilerInput ->
196+ Eff effs Context
197+ resolveCreateContext ci = do
198+ ctxs <- traverse module2Context (ci ^. # modules)
199+ pure $ mconcat ctxs
200+
201+ module2Context ::
202+ forall effs .
203+ Member (State (M. Map Variable P. TyDef )) effs =>
204+ Member Err effs =>
205+ P. Module ->
206+ Eff effs Context
207+ module2Context m = do
208+ let typeDefinitions = m ^. # typeDefs
209+ ctxs <- runReader (m ^. # moduleName) $ do
210+ traverse (tyDef2Context (moduleName2ModName (m ^. # moduleName))) typeDefinitions
211+ pure $ mconcat ctxs
212+
213+ -- | Creates a Context entry from one type definition.
214+ tyDef2Context ::
215+ forall effs .
216+ Member (Reader P. ModuleName ) effs =>
217+ Member (State (M. Map Variable P. TyDef )) effs =>
218+ Member Err effs =>
219+ ModName ->
220+ P. TyDef ->
221+ Eff effs Context
222+ tyDef2Context curModName tyDef = do
223+ r@ (v, _) <- tyDef2NameAndKind curModName tyDef
224+ associateName v tyDef
225+ pure $ mempty & context .~ uncurry M. singleton r
226+ where
227+ -- Ads the name to our map - we can use its SourceLocation in the case of a
228+ -- double use. If it's already in our map - that means we've double declared it.
229+ associateName :: Variable -> P. TyDef -> Eff effs ()
230+ associateName v curTyDef = do
231+ modName <- ask
232+ maps <- get @ (M. Map Variable P. TyDef )
233+ case maps M. !? v of
234+ Just otherTyDef ->
235+ throwError . PT. CompKindCheckError $ PT. MultipleTyDefError modName [otherTyDef, curTyDef]
236+ Nothing -> modify (M. insert v curTyDef)
237+
238+ {- | Converts the Proto Module name to a local modname - dropping the
239+ information.
240+ -}
220241moduleName2ModName :: P. ModuleName -> ModName
221242moduleName2ModName mName = (\ p -> p ^. # name) <$> mName ^. # parts
222243
@@ -227,11 +248,6 @@ tyDef2NameAndKind curModName tyDef = do
227248 let k = tyAbsLHS2Kind (tyDef ^. # tyAbs)
228249 pure (name, k)
229250
230- tyDef2Context :: forall effs . ModName -> P. TyDef -> Eff effs Context
231- tyDef2Context curModName tyDef = do
232- r <- tyDef2NameAndKind curModName tyDef
233- pure $ mempty & context .~ uncurry M. singleton r
234-
235251tyAbsLHS2Kind :: P. TyAbs -> Kind
236252tyAbsLHS2Kind tyAbs = foldWithArrow $ pKind2Type . (\ x -> x ^. # argKind) <$> (tyAbs ^. # tyArgs)
237253
0 commit comments