@@ -18,9 +18,10 @@ import Control.Monad.Freer.Error (Error, runError, throwError)
1818import Control.Monad.Freer.Reader (Reader , ask , runReader )
1919import Control.Monad.Freer.State (State , evalState , modify )
2020import Control.Monad.Freer.TH (makeEffect )
21+ import Control.Monad.Freer.Writer (Writer , runWriter , tell )
2122import Data.Foldable (Foldable (foldl' , toList ), traverse_ )
2223import Data.Map qualified as M
23- import Data.Text (Text , intercalate )
24+ import Data.Text (Text , pack )
2425import LambdaBuffers.Compiler.KindCheck.Context (Context )
2526import LambdaBuffers.Compiler.KindCheck.Inference (
2627 InferErr (
@@ -40,6 +41,7 @@ import LambdaBuffers.Compiler.KindCheck.Type (Type (App), tyOpaque, tyProd, tySu
4041import LambdaBuffers.Compiler.KindCheck.Variable (Variable (ForeignRef , LocalRef ))
4142import LambdaBuffers.Compiler.ProtoCompat ()
4243import LambdaBuffers.Compiler.ProtoCompat.Types qualified as PC
44+ import Prettyprinter (Pretty (pretty ))
4345
4446--------------------------------------------------------------------------------
4547-- Types
@@ -135,30 +137,91 @@ localStrategy = reinterpret $ \case
135137 -- KCClass _ctx _classDef -> pure ()
136138 -}
137139
140+ -- | Internal to External term association map ~ a mapping between a Variable and the term it originated from. Allows us to throw meaningful errors.
141+ type IETermMap = M. Map Variable (Either PC. TyVar PC. TyRef )
142+
143+ type HandleErrorEnv a = Eff '[Reader ModName , Writer IETermMap ] a
144+
138145runKindCheck :: forall effs {a }. Member Err effs => Eff (KindCheck ': effs ) a -> Eff effs a
139146runKindCheck = interpret $ \ case
140- TypesFromTyDef moduleName tydef -> runReader moduleName (tyDef2Types tydef)
141- InferTypeKind _modName tyDef ctx ty -> either (handleErr tyDef) pure $ infer ctx ty
142- CheckKindConsistency mname def ctx k -> runReader mname $ resolveKindConsistency def ctx k
147+ TypesFromTyDef modName tydef -> runReader modName (tyDef2Types tydef)
148+ InferTypeKind modName tyDef ctx ty -> either (handleErr modName tyDef) pure $ infer ctx ty
149+ CheckKindConsistency modName def ctx k -> runReader modName $ resolveKindConsistency def ctx k
143150 where
144- handleErr :: forall {b }. PC. TyDef -> InferErr -> Eff effs b
145- handleErr td = \ case
146- InferUnboundTermErr uA ->
147- throwError . PC. CompKindCheckError $ PC. UnboundTermError (tyDef2TyName td) (var2VarName uA)
151+ handleErr :: forall {b }. ModName -> PC. TyDef -> InferErr -> Eff effs b
152+ handleErr modName td = \ case
153+ InferUnboundTermErr uA -> do
154+ tt <- getTermType modName td uA
155+ throwError . PC. CompKindCheckError $ case tt of
156+ Right r -> PC. UnboundTyRefError td r
157+ Left l -> PC. UnboundTyVarError td l
148158 InferUnifyTermErr (I. Constraint (k1, k2)) ->
149159 throwError . PC. CompKindCheckError $ PC. IncorrectApplicationError (tyDef2TyName td) (kind2ProtoKind k1) (kind2ProtoKind k2)
150160 InferRecursiveSubstitutionErr _ ->
151161 throwError . PC. CompKindCheckError $ PC. RecursiveKindError $ tyDef2TyName td
152162 InferImpossibleErr t ->
153163 throwError . PC. InternalError $ t
154164
155- var2VarName = \ case
156- LocalRef n -> PC. VarName n emptySourceInfo
157- ForeignRef m s -> PC. VarName (intercalate " ." m <> s) emptySourceInfo
165+ getTermType :: ModName -> PC. TyDef -> Variable -> Eff effs (Either PC. TyVar PC. TyRef )
166+ getTermType modName td va = do
167+ let termMap = snd . run . runWriter . runReader modName $ tyDef2Map td
168+ case termMap M. !? va of
169+ Just x -> pure x
170+ Nothing ->
171+ throwError . PC. InternalError . pack . unlines $
172+ [ " Could not find the corresponding source info for:"
173+ , show . pretty $ va
174+ , " This should never happen."
175+ , " Please report error."
176+ ]
177+ where
178+ {- Conversion functions that associate a variable with its KC term.
179+ The Monad has a Writer Map instance which is then used to retrieve sourceInfo
180+ about the term.
181+ -}
182+
183+ tyDef2Map :: PC. TyDef -> HandleErrorEnv ()
184+ tyDef2Map = tyAbs2Map . view # tyAbs
185+
186+ -- Note(cstml): Is there any purpose for anything from the tyArg - be sure to cover with tests.
187+ tyAbs2Map :: PC. TyAbs -> HandleErrorEnv ()
188+ tyAbs2Map tyAbs = tyBody2Map (tyAbs ^. # tyBody)
189+
190+ tyBody2Map :: PC. TyBody -> HandleErrorEnv ()
191+ tyBody2Map = \ case
192+ PC. OpaqueI _ -> pure ()
193+ PC. SumI s -> sum2Map s
194+
195+ sum2Map :: PC. Sum -> HandleErrorEnv ()
196+ sum2Map (PC. Sum constr _) = traverse_ constr2Map $ M. elems constr
197+
198+ constr2Map :: PC. Constructor -> HandleErrorEnv ()
199+ constr2Map = product2Map . view # product
200+
201+ product2Map :: PC. Product -> HandleErrorEnv ()
202+ product2Map = \ case
203+ PC. RecordI r -> record2Map r
204+ PC. TupleI t -> tuple2Map t
158205
159- emptySourceInfo = PC. SourceInfo mempty emptySourcePosition emptySourcePosition
206+ record2Map :: PC. Record -> HandleErrorEnv ()
207+ record2Map r = traverse_ field2Map $ r ^. # fields
160208
161- emptySourcePosition = PC. SourcePosition 0 0
209+ field2Map :: PC. Field -> HandleErrorEnv ()
210+ field2Map = ty2Map . view # fieldTy
211+
212+ ty2Map :: PC. Ty -> HandleErrorEnv ()
213+ ty2Map = \ case
214+ PC. TyVarI tvar ->
215+ tell @ IETermMap $ M. singleton (tyVar2Variable tvar) (Left tvar)
216+ PC. TyAppI tapp -> do
217+ ty2Map $ tapp ^. # tyFunc
218+ traverse_ ty2Map $ tapp ^. # tyArgs
219+ PC. TyRefI tyref -> do
220+ var <- tyRef2Variable tyref
221+ tell @ IETermMap $ M. singleton var (Right tyref)
222+
223+ tuple2Map :: PC. Tuple -> HandleErrorEnv ()
224+ tuple2Map = traverse_ ty2Map . view # fields
162225
163226-- Resolvers
164227
@@ -275,7 +338,7 @@ pKind2Kind k =
275338 case k ^. # kind of
276339 PC. KindRef PC. KType -> Type
277340 PC. KindArrow l r -> pKind2Kind l :->: pKind2Kind r
278- -- NOTE(cstml): What is an Kind type meant to mean?
341+ -- NOTE(cstml): What is an undefined Kind type meant to mean?
279342 _ -> error " Fixme undefined type"
280343
281344-- =============================================================================
@@ -388,7 +451,10 @@ tyVar2Type ::
388451 forall eff .
389452 PC. TyVar ->
390453 Eff eff Type
391- tyVar2Type tv = pure . Var . LocalRef $ (tv ^. # varName . # name)
454+ tyVar2Type = pure . Var . tyVar2Variable
455+
456+ tyVar2Variable :: PC. TyVar -> Variable
457+ tyVar2Variable = LocalRef . view (# varName . # name)
392458
393459tyApp2Type ::
394460 forall eff .
@@ -405,26 +471,34 @@ tyRef2Type ::
405471 Members '[Reader ModName , Err ] eff =>
406472 PC. TyRef ->
407473 Eff eff Type
408- tyRef2Type = \ case
409- PC. LocalI lref -> localTyRef2Type lref
410- PC. ForeignI fref -> foreignTyRef2Type fref
474+ tyRef2Type = fmap Var . tyRef2Variable
411475
412- localTyRef2Type ::
476+ tyRef2Variable ::
413477 forall eff .
414- Members '[Reader ModName , Err ] eff =>
478+ Members '[Reader ModName ] eff =>
479+ PC. TyRef ->
480+ Eff eff Variable
481+ tyRef2Variable = \ case
482+ PC. LocalI lref -> localTyRef2Variable lref
483+ PC. ForeignI fref -> foreignTyRef2Variable fref
484+
485+ localTyRef2Variable ::
486+ forall eff .
487+ Members '[Reader ModName ] eff =>
415488 PC. LocalRef ->
416- Eff eff Type
417- localTyRef2Type ltr = do
489+ Eff eff Variable
490+ localTyRef2Variable ltr = do
418491 moduleName <- ask
419- pure . Var $ ForeignRef moduleName (ltr ^. # tyName . # name)
492+ pure $ ForeignRef moduleName (ltr ^. # tyName . # name)
420493
421- foreignTyRef2Type ::
494+ foreignTyRef2Variable ::
422495 forall eff .
496+ Members '[Reader ModName ] eff =>
423497 PC. ForeignRef ->
424- Eff eff Type
425- foreignTyRef2Type ftr = do
498+ Eff eff Variable
499+ foreignTyRef2Variable ftr = do
426500 let moduleName = moduleName2ModName (ftr ^. # moduleName)
427- pure $ Var $ ForeignRef moduleName (ftr ^. # tyName . # name)
501+ pure $ ForeignRef moduleName (ftr ^. # tyName . # name)
428502
429503-- =============================================================================
430504-- X To Canonical type conversion functions.
0 commit comments