1- {-# LANGUAGE DuplicateRecordFields #-}
2- {-# LANGUAGE OverloadedLabels #-}
3- {-# LANGUAGE RecordWildCards #-}
4- {-# LANGUAGE TemplateHaskell #-}
5-
61module LambdaBuffers.Compiler.KindCheck (
2+ -- * Kindchecking functions.
73 check ,
84 check_ ,
9- foldWithSum ,
10-
11- -- * Testing Utils
125
13- -- * Utilities -- exported for testing
6+ -- * Testing Utils.
7+ foldWithSum ,
148 foldWithArrow ,
159 foldWithProduct ,
1610) where
@@ -21,21 +15,65 @@ import Control.Monad.Freer (Eff, Members, reinterpret, run)
2115import Control.Monad.Freer.Error (Error , runError , throwError )
2216import Control.Monad.Freer.Reader (Reader , ask , runReader )
2317import Control.Monad.Freer.TH (makeEffect )
18+ import Data.Foldable (traverse_ )
19+ import Data.List.NonEmpty (NonEmpty ((:|) ), uncons , (<|) )
20+ import Data.Map qualified as M
2421import Data.Text (Text , intercalate )
25- import LambdaBuffers.Compiler.KindCheck.Context (Context , getAllContext )
22+ import LambdaBuffers.Compiler.KindCheck.Context (Context )
2623import LambdaBuffers.Compiler.KindCheck.Inference (
24+ InferErr (
25+ InferImpossibleErr ,
26+ InferRecursiveSubstitutionErr ,
27+ InferUnboundTermErr ,
28+ InferUnifyTermErr
29+ ),
2730 Kind (Type , (:->:) ),
2831 Type (Abs , Var ),
2932 context ,
3033 infer ,
3134 )
35+ import LambdaBuffers.Compiler.KindCheck.Inference qualified as I
3236import LambdaBuffers.Compiler.KindCheck.Type (Type (App ))
33- import LambdaBuffers.Compiler.KindCheck.Variable (Var )
34- import LambdaBuffers.Compiler.ProtoCompat qualified as P
35-
36- import Data.Foldable (traverse_ )
37- import Data.List.NonEmpty (NonEmpty ((:|) ), uncons , (<|) )
38- import Data.Map qualified as M
37+ import LambdaBuffers.Compiler.KindCheck.Variable (Variable (ForeignRef , LocalRef ))
38+ import 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+ )
76+ import LambdaBuffers.Compiler.ProtoCompat.Types qualified as PT
3977
4078--------------------------------------------------------------------------------
4179-- Types
@@ -44,11 +82,11 @@ import Data.Map qualified as M
4482-- - double declaration of a type
4583
4684-- | Kind Check failure types.
47- type KindCheckFailure = P. KindCheckErr
85+ type CompilerErr = P. CompilerError
4886
49- type Err = Error KindCheckFailure
87+ type Err = Error CompilerErr
5088
51- type ModName = Text
89+ type ModName = [ Text ]
5290
5391-- | Main interface to the Kind Checker.
5492data Check a where
@@ -75,20 +113,24 @@ data KindCheck a where
75113 KindFromTyDef :: ModName -> P. TyDef -> KindCheck Type
76114 InferTypeKind :: ModName -> P. TyDef -> Context -> Type -> KindCheck Kind
77115 CheckKindConsistency :: ModName -> P. TyDef -> Context -> Kind -> KindCheck Kind
116+
117+ -- FIXME(cstml) add check for Context Consistency
118+ -- FIXME(cstml) add check for Double Declaration
119+ -- TyDefToTypes :: ModName -> P.TyDef -> KindCheck [Type]
78120makeEffect ''KindCheck
79121
80122--------------------------------------------------------------------------------
81123
82- runCheck :: Eff (Check ': '[] ) a -> Either KindCheckFailure a
124+ runCheck :: Eff (Check ': '[] ) a -> Either CompilerErr a
83125runCheck = run . runError . runKindCheck . localStrategy . moduleStrategy . globalStrategy
84126
85127-- | Run the check - return the validated context or the failure.
86- check :: P. CompilerInput -> Either KindCheckFailure Context
87- check = runCheck . kCheck
128+ check :: P. CompilerInput -> PT. CompilerOutput
129+ check = fmap ( const PT. CompilerResult ) . runCheck . kCheck
88130
89131-- | Run the check - drop the result if it succeeds.
90- check_ :: P. CompilerInput -> Either KindCheckFailure ()
91- check_ = void . check
132+ check_ :: P. CompilerInput -> Either CompilerErr ()
133+ check_ = void . runCheck . kCheck
92134
93135--------------------------------------------------------------------------------
94136
@@ -120,8 +162,28 @@ localStrategy = reinterpret $ \case
120162runKindCheck :: Eff '[KindCheck ] a -> Eff '[Err ] a
121163runKindCheck = reinterpret $ \ case
122164 KindFromTyDef moduleName tydef -> runReader moduleName (tyDef2Type tydef)
123- InferTypeKind _modName tyDef ctx ty -> either (throwError . P. InferenceFailure tyDef) pure $ infer ctx ty
165+ -- TyDefToTypes moduleName tydef -> runReader moduleName (tyDef2Types tydef)
166+ InferTypeKind _modName tyDef ctx ty -> either (handleErr tyDef) pure $ infer ctx ty
124167 CheckKindConsistency mname def ctx k -> runReader mname $ resolveKindConsistency def ctx k
168+ where
169+ handleErr :: forall a . P. TyDef -> InferErr -> Eff '[Err ] a
170+ handleErr td = \ case
171+ InferUnboundTermErr uA ->
172+ throwError . P. CompKindCheckError $ P. UnboundTermError (tyDef2TyName td) (var2VarName uA)
173+ InferUnifyTermErr (I. Constraint (k1, k2)) ->
174+ throwError . P. CompKindCheckError $ P. IncorrectApplicationError (tyDef2TyName td) (kind2ProtoKind k1) (kind2ProtoKind k2)
175+ InferRecursiveSubstitutionErr _ ->
176+ throwError . P. CompKindCheckError $ P. RecursiveKindError $ tyDef2TyName td
177+ InferImpossibleErr t ->
178+ throwError . P. InternalError $ t
179+
180+ var2VarName = \ case
181+ LocalRef n -> P. VarName n emptySourceInfo
182+ ForeignRef m s -> P. VarName (intercalate " ." m <> s) emptySourceInfo
183+
184+ emptySourceInfo = P. SourceInfo mempty emptySourcePosition emptySourcePosition
185+
186+ emptySourcePosition = P. SourcePosition 0 0
125187
126188-- Resolvers
127189
@@ -132,27 +194,36 @@ resolveKindConsistency ::
132194 Context ->
133195 Kind ->
134196 Eff effs Kind
135- resolveKindConsistency tydef ctx inferredKind = do
197+ resolveKindConsistency tydef _ctx inferredKind = do
136198 mName <- ask @ ModName
137- (n, k) <- tyDef2NameAndKind mName tydef
138- guard $ k == inferredKind
139- guard $ getAllContext ctx M. !? n == Just inferredKind
199+ let tyName = tyDef2TyName tydef
200+ (_, k) <- tyDef2NameAndKind mName tydef
201+ guard tyName k inferredKind
140202 pure inferredKind
141203 where
142- guard b = if b then pure () else throwError $ P. InconsistentTypeErr tydef
204+ guard :: P. TyName -> Kind -> Kind -> Eff effs ()
205+ guard n i d
206+ | i == d = pure ()
207+ | otherwise =
208+ throwError . P. CompKindCheckError $
209+ P. InconsistentTypeError n (kind2ProtoKind i) (kind2ProtoKind d)
143210
144211resolveCreateContext :: forall effs . P. CompilerInput -> Eff effs Context
145212resolveCreateContext ci = mconcat <$> traverse module2Context (ci ^. # modules)
146213
214+ tyDef2TyName :: P. TyDef -> P. TyName
215+ tyDef2TyName (P. TyDef n _ _) = n
216+
147217module2Context :: forall effs . P. Module -> Eff effs Context
148- module2Context m = mconcat <$> traverse (tyDef2Context (flattenModuleName (m ^. # moduleName))) (m ^. # typeDefs)
218+ module2Context m = mconcat <$> traverse (tyDef2Context (moduleName2ModName (m ^. # moduleName))) (m ^. # typeDefs)
149219
150- flattenModuleName :: P. ModuleName -> Text
151- flattenModuleName mName = intercalate " . " $ (\ p -> p ^. # name) <$> mName ^. # parts
220+ moduleName2ModName :: P. ModuleName -> ModName
221+ moduleName2ModName mName = (\ p -> p ^. # name) <$> mName ^. # parts
152222
153- tyDef2NameAndKind :: forall effs . ModName -> P. TyDef -> Eff effs (ModName , Kind )
223+ tyDef2NameAndKind :: forall effs . ModName -> P. TyDef -> Eff effs (Variable , Kind )
154224tyDef2NameAndKind curModName tyDef = do
155- let name = curModName <> " ." <> (tyDef ^. # tyName . # name) -- name is qualified
225+ -- all names are qualified
226+ let name = ForeignRef curModName (tyDef ^. # tyName . # name)
156227 let k = tyAbsLHS2Kind (tyDef ^. # tyAbs)
157228 pure (name, k)
158229
@@ -205,8 +276,8 @@ tyArgs2Type = \case
205276 f <- tyArgs2Type xs
206277 pure $ \ c -> Abs (tyArg2Var x) (f c)
207278
208- tyArg2Var :: P. TyArg -> Var
209- tyArg2Var = view (# argName . # name)
279+ tyArg2Var :: P. TyArg -> Variable
280+ tyArg2Var = LocalRef . view (# argName . # name)
210281
211282tyAbsRHS2Type ::
212283 forall eff .
@@ -221,7 +292,7 @@ tyBody2Type ::
221292 P. TyBody ->
222293 Eff eff Type
223294tyBody2Type = \ case
224- P. OpaqueI _ -> pure $ Var " Opaque"
295+ P. OpaqueI _ -> pure $ Var $ LocalRef " Opaque"
225296 P. SumI s -> sum2Type s
226297
227298sum2Type ::
@@ -262,7 +333,7 @@ tuple2Type ::
262333tuple2Type tu = do
263334 tup <- traverse ty2Type $ tu ^. # fields
264335 case tup of
265- [] -> pure $ Var " 𝟙"
336+ [] -> pure $ Var $ LocalRef " 𝟙"
266337 x : xs -> pure . foldWithProduct $ x :| xs
267338
268339field2Type ::
@@ -286,7 +357,7 @@ tyVar2Type ::
286357 forall eff .
287358 P. TyVar ->
288359 Eff eff Type
289- tyVar2Type tv = pure . Var $ (tv ^. # varName . # name)
360+ tyVar2Type tv = pure . Var . LocalRef $ (tv ^. # varName . # name)
290361
291362tyApp2Type ::
292363 forall eff .
@@ -314,27 +385,64 @@ localTyRef2Type ::
314385 Eff eff Type
315386localTyRef2Type ltr = do
316387 moduleName <- ask
317- pure $ Var $ moduleName <> " . " <> (ltr ^. # tyName . # name)
388+ pure . Var $ ForeignRef moduleName (ltr ^. # tyName . # name)
318389
319390foreignTyRef2Type ::
320391 forall eff .
321392 P. ForeignRef ->
322393 Eff eff Type
323394foreignTyRef2Type ftr = do
324- let moduleName = flattenModuleName (ftr ^. # moduleName)
325- pure $ Var $ moduleName <> " . " <> (ftr ^. # tyName . # name)
395+ let moduleName = moduleName2ModName (ftr ^. # moduleName)
396+ pure $ Var $ ForeignRef moduleName (ftr ^. # tyName . # name)
326397
398+ -- =============================================================================
399+ -- X To Canonical type conversion functions.
400+ {-
401+ -- | TyDef to Kind Canonical representation - sums not folded - therefore we get constructor granularity. Might use in a different implementation for more granular errors.
402+ tyDef2Types ::
403+ forall eff.
404+ Members '[Reader ModName, Err] eff =>
405+ P.TyDef ->
406+ Eff eff [Type]
407+ tyDef2Types tyde = do
408+ f <- tyAbsLHS2Type (tyde ^. #tyAbs) -- abstraction
409+ cs <- tyAbsRHS2Types (tyde ^. #tyAbs) --
410+ pure $ f <$> cs
411+
412+ tyAbsRHS2Types ::
413+ forall eff.
414+ Members '[Reader ModName, Err] eff =>
415+ P.TyAbs ->
416+ Eff eff [Type]
417+ tyAbsRHS2Types tyab = tyBody2Types (tyab ^. #tyBody)
418+
419+ tyBody2Types ::
420+ forall eff.
421+ Members '[Reader ModName, Err] eff =>
422+ P.TyBody ->
423+ Eff eff [Type]
424+ tyBody2Types = \case
425+ P.OpaqueI _ -> pure [Var $ LocalRef "Opaque"]
426+ P.SumI s -> sum2Types s
427+
428+ sum2Types ::
429+ forall eff.
430+ Members '[Reader ModName, Err] eff =>
431+ P.Sum ->
432+ Eff eff [Type]
433+ sum2Types su = NonEmpty.toList <$> traverse constructor2Type (su ^. #constructors)
434+ -}
327435--------------------------------------------------------------------------------
328436-- Utilities
329437
330438foldWithApp :: NonEmpty Type -> Type
331439foldWithApp = foldWithBinaryOp App
332440
333441foldWithProduct :: NonEmpty Type -> Type
334- foldWithProduct = foldWithBinaryOp $ App . App (Var " Π" )
442+ foldWithProduct = foldWithBinaryOp $ App . App (Var $ LocalRef " Π" )
335443
336444foldWithSum :: NonEmpty Type -> Type
337- foldWithSum = foldWithBinaryOp $ App . App (Var " Σ" )
445+ foldWithSum = foldWithBinaryOp $ App . App (Var $ LocalRef " Σ" )
338446
339447-- | Generic way of folding.
340448foldWithBinaryOp :: (Type -> Type -> Type ) -> NonEmpty Type -> Type
@@ -343,4 +451,4 @@ foldWithBinaryOp op ne = case uncons ne of
343451 (x, Just xs) -> op x $ foldWithBinaryOp op xs
344452
345453module2ModuleName :: P. Module -> ModName
346- module2ModuleName = flattenModuleName . (^. # moduleName)
454+ module2ModuleName = moduleName2ModName . (^. # moduleName)
0 commit comments