Skip to content

Commit 40514f3

Browse files
committed
update: working errors
1 parent bd7bb39 commit 40514f3

File tree

4 files changed

+131
-48
lines changed

4 files changed

+131
-48
lines changed

lambda-buffers-compiler/src/LambdaBuffers/Compiler/KindCheck.hs

Lines changed: 101 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ import Control.Monad.Freer.Error (Error, runError, throwError)
1818
import Control.Monad.Freer.Reader (Reader, ask, runReader)
1919
import Control.Monad.Freer.State (State, evalState, modify)
2020
import Control.Monad.Freer.TH (makeEffect)
21+
import Control.Monad.Freer.Writer (Writer, runWriter, tell)
2122
import Data.Foldable (Foldable (foldl', toList), traverse_)
2223
import Data.Map qualified as M
23-
import Data.Text (Text, intercalate)
24+
import Data.Text (Text, pack)
2425
import LambdaBuffers.Compiler.KindCheck.Context (Context)
2526
import LambdaBuffers.Compiler.KindCheck.Inference (
2627
InferErr (
@@ -40,6 +41,7 @@ import LambdaBuffers.Compiler.KindCheck.Type (Type (App), tyOpaque, tyProd, tySu
4041
import LambdaBuffers.Compiler.KindCheck.Variable (Variable (ForeignRef, LocalRef))
4142
import LambdaBuffers.Compiler.ProtoCompat ()
4243
import 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+
138145
runKindCheck :: forall effs {a}. Member Err effs => Eff (KindCheck ': effs) a -> Eff effs a
139146
runKindCheck = 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

393459
tyApp2Type ::
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.

lambda-buffers-compiler/src/LambdaBuffers/Compiler/ProtoCompat/FromProto.hs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -666,43 +666,51 @@ instance IsMessage P.KindCheckError PC.KindCheckError where
666666
fromProto kce =
667667
case kce ^. P.maybe'kindCheckError of
668668
Just x -> case x of
669-
P.KindCheckError'UnboundTermError' err ->
670-
PC.UnboundTermError
671-
<$> fromProto (err ^. P.tyName)
672-
<*> fromProto (err ^. P.varName)
673-
P.KindCheckError'UnificationError err ->
669+
P.KindCheckError'UnboundTyVarError' err ->
670+
PC.UnboundTyVarError
671+
<$> fromProto (err ^. P.tyDef)
672+
<*> fromProto (err ^. P.tyVar)
673+
P.KindCheckError'UnboundTyRefError' err ->
674+
PC.UnboundTyRefError
675+
<$> fromProto (err ^. P.tyDef)
676+
<*> fromProto (err ^. P.tyRef)
677+
P.KindCheckError'ImpossibleUnificationError' err ->
674678
PC.IncorrectApplicationError
675679
<$> fromProto (err ^. P.tyName)
676-
<*> fromProto (err ^. P.tyKind1)
677-
<*> fromProto (err ^. P.tyKind2)
678-
P.KindCheckError'RecursiveSubsError err ->
680+
<*> fromProto (err ^. P.tyKindLhs)
681+
<*> fromProto (err ^. P.tyKindRhs)
682+
P.KindCheckError'RecursiveKindError' err ->
679683
PC.RecursiveKindError
680684
<$> fromProto (err ^. P.tyName)
681685
P.KindCheckError'InconsistentTypeError' err ->
682686
PC.InconsistentTypeError
683687
<$> fromProto (err ^. P.tyName)
684-
<*> fromProto (err ^. P.inferredKind)
685-
<*> fromProto (err ^. P.definedKind)
688+
<*> fromProto (err ^. P.actualKind)
689+
<*> fromProto (err ^. P.expectedKind)
686690
Nothing -> throwOneOfError (messageName (Proxy @P.KindCheckError)) "kind_check_error"
687691

688692
toProto = \case
689-
PC.UnboundTermError tyname varname ->
693+
PC.UnboundTyVarError tydef tyvar ->
694+
defMessage
695+
& (P.unboundTyVarError . P.tyDef) .~ toProto tydef
696+
& (P.unboundTyVarError . P.tyVar) .~ toProto tyvar
697+
PC.UnboundTyRefError tydef tyref ->
690698
defMessage
691-
& (P.unboundTermError . P.tyName) .~ toProto tyname
692-
& (P.unboundTermError . P.varName) .~ toProto varname
699+
& (P.unboundTyRefError . P.tyDef) .~ toProto tydef
700+
& (P.unboundTyRefError . P.tyRef) .~ toProto tyref
693701
PC.IncorrectApplicationError name k1 k2 ->
694702
defMessage
695-
& (P.unificationError . P.tyName) .~ toProto name
696-
& (P.unificationError . P.tyKind1) .~ toProto k1
697-
& (P.unificationError . P.tyKind2) .~ toProto k2
703+
& (P.impossibleUnificationError . P.tyName) .~ toProto name
704+
& (P.impossibleUnificationError . P.tyKindLhs) .~ toProto k1
705+
& (P.impossibleUnificationError . P.tyKindRhs) .~ toProto k2
698706
PC.RecursiveKindError err ->
699707
defMessage
700-
& (P.recursiveSubsError . P.tyName) .~ toProto err
708+
& (P.recursiveKindError . P.tyName) .~ toProto err
701709
PC.InconsistentTypeError name ki kd ->
702710
defMessage
703711
& (P.inconsistentTypeError . P.tyName) .~ toProto name
704-
& (P.inconsistentTypeError . P.inferredKind) .~ toProto ki
705-
& (P.inconsistentTypeError . P.definedKind) .~ toProto kd
712+
& (P.inconsistentTypeError . P.actualKind) .~ toProto ki
713+
& (P.inconsistentTypeError . P.expectedKind) .~ toProto kd
706714

707715
instance IsMessage P.CompilerError PC.CompilerError where
708716
fromProto _ = throwInternalError "fromProto CompilerError not implemented"

lambda-buffers-compiler/src/LambdaBuffers/Compiler/ProtoCompat/Types.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ instance Arbitrary CompilerInput where
316316
fn n = CompilerInput <$> resize n arbitrary
317317

318318
data KindCheckError
319-
= UnboundTermError TyName VarName
319+
= UnboundTyVarError TyDef TyVar
320+
| UnboundTyRefError TyDef TyRef
320321
| IncorrectApplicationError TyName Kind Kind
321322
| RecursiveKindError TyName
322323
| InconsistentTypeError TyName Kind Kind

lambda-buffers-proto/compiler.proto

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ message KindCheckError {
639639
// Unbound variable ty_var detected in term ty_def.
640640
message UnboundTyVarError {
641641
TyDef ty_def = 1;
642-
TyVar var_name = 2;
642+
TyVar ty_var = 2;
643643
}
644644

645645
// Unbound variable ty_ref detected in term ty_def.

0 commit comments

Comments
 (0)