1+ {-# LANGUAGE DuplicateRecordFields #-}
2+ {-# LANGUAGE OverloadedLabels #-}
3+ {-# LANGUAGE RecordWildCards #-}
14{-# LANGUAGE TemplateHaskell #-}
25
36{- | Note: At the moment the Kind Checker disregards multiple Modules for
@@ -6,64 +9,33 @@ simplicity of testing and developing. This will be changed ASAP. :fixme:
69module LambdaBuffers.Compiler.KindCheck (
710 KindCheckFailure (.. ),
811 runKindCheck ,
9- TypeDefinition (.. ),
1012
1113 -- * Testing Utils
1214 kindCheckType ,
1315 runKindCheckEff ,
1416) where
1517
1618import Control.Exception (Exception )
17- import Control.Lens (folded , makeLenses , to , (&) , (.~) , (^.) , (^..) )
18- import Control.Monad.Freer (Eff , interpret , run )
19+ import Control.Lens ((&) , (.~) , (^.) )
1920import Control.Monad.Freer.Error (Error , runError , throwError )
2021import Control.Monad.Freer.TH (makeEffect )
21- import Data.Text (Text , intercalate , unpack )
22+ import Data.Text (Text , intercalate )
2223import LambdaBuffers.Compiler.KindCheck.Inference (
2324 Context ,
2425 InferErr ,
2526 Kind (Type , (:->:) ),
26- Type (Abs , App , Var ),
27+ Type (Var ),
2728 context ,
2829 infer ,
2930 )
3031
31- import Control.Monad (void )
32- import Data.Traversable (for )
33- import Proto.Compiler (
34- Product'NTuple ,
35- Product'Product (Product'Ntuple , Product'Record' ),
36- Product'Record ,
37- Sum ,
38- Ty ,
39- Ty'Ty (Ty'TyApp , Ty'TyRef , Ty'TyVar ),
40- TyApp ,
41- TyBody'TyBody (TyBody'Opaque , TyBody'Sum ),
42- TyDef ,
43- TyRef ,
44- TyRef'TyRef (TyRef'ForeignTyRef , TyRef'LocalTyRef ),
45- )
46- import Proto.Compiler_Fields as PF (
47- constrName ,
48- constructors ,
49- fieldTy ,
50- fields ,
51- maybe'product ,
52- maybe'ty ,
53- maybe'tyBody ,
54- maybe'tyRef ,
55- moduleName ,
56- name ,
57- parts ,
58- product ,
59- tyAbs ,
60- tyArgs ,
61- tyBody ,
62- tyFunc ,
63- tyName ,
64- tyVars ,
65- varName ,
66- )
32+ import Control.Monad
33+ import Control.Monad.Freer
34+ import LambdaBuffers.Common.ProtoCompat qualified as P
35+
36+ import Data.Foldable
37+
38+ import Data.Map qualified as M
6739
6840--------------------------------------------------------------------------------
6941-- Types
@@ -72,54 +44,139 @@ import Proto.Compiler_Fields as PF (
7244data KindCheckFailure
7345 = CheckFailure String
7446 | LookupVarFailure Text
75- | LookupRefFailure TyRef
47+ | LookupRefFailure P. TyRef
7648 | AppWrongArgKind Kind Kind -- Expected Kind got Kind
7749 | AppToManyArgs Int
7850 | InvalidProto Text
7951 | AppNoArgs -- No args
8052 | InvalidType
81- | InferenceFailed TypeDefinition InferErr
53+ | InferenceFailed P. TyDef InferErr
8254 deriving stock (Show , Eq )
8355
8456instance Exception KindCheckFailure
8557
86- {- | Validated Type Definition.
87- :fixme: Add to compiler.proto
88- -}
89- data TypeDefinition = TypeDefinition
90- { _td'name :: String
91- , _td'variables :: [String ]
92- , _td'sop :: Type
93- }
94- deriving stock (Show , Eq )
58+ type Err = Error KindCheckFailure
59+
60+ -- | Main interface to the Kind Checker.
61+ data Check a where
62+ KindCheck :: P. CompilerInput -> Check ()
63+
64+ makeEffect ''Check
65+
66+ -- | Interactions that happen at the level of the Global Checker.
67+ data GlobalCheck a where
68+ CreateContext :: P. CompilerInput -> GlobalCheck Context
69+ ValidateModule :: Context -> P. Module -> GlobalCheck ()
9570
96- makeLenses 'TypeDefinition
71+ makeEffect ''GlobalCheck
72+
73+ -- | Interactions that happen at the level of the
74+ data ModuleCheck a where -- Module
75+ KCTypeDefinition :: Context -> P. TyDef -> ModuleCheck Kind
76+ KCClassInstance :: Context -> P. InstanceClause -> ModuleCheck ()
77+ KCClass :: Context -> P. ClassDef -> ModuleCheck ()
78+
79+ makeEffect ''ModuleCheck
9780
9881data KindCheck a where
99- ValidateInput :: [ TyDef ] -> KindCheck [ TypeDefinition ]
100- CreateContext :: [ TypeDefinition ] -> KindCheck Context
101- KindCheck :: Context -> TypeDefinition -> KindCheck Kind
82+ KindFromTyDef :: P. TyDef -> KindCheck Type
83+ InferTypeKind :: Context -> Type -> KindCheck Kind
84+ CheckKindConsistency :: P. TyDef -> Context -> Kind -> KindCheck Kind
10285
10386makeEffect ''KindCheck
10487
105- type KindCheckFailEff = '[Error KindCheckFailure ]
106- type KindCheckEff = KindCheck ': KindCheckFailEff
88+ type Transform x y = forall effs {a }. Eff (x ': effs ) a -> Eff (y ': effs ) a
89+
90+ -- Transformation strategies
91+
92+ globalStrategy :: Transform Check GlobalCheck
93+ globalStrategy = reinterpret $ \ case
94+ KindCheck ci -> do
95+ ctx <- createContext ci
96+ void $ validateModule ctx `traverse` (ci ^. # modules)
97+
98+ moduleStrategy :: Transform GlobalCheck ModuleCheck
99+ moduleStrategy = reinterpret $ \ case
100+ CreateContext ci -> resolveCreateContext ci
101+ ValidateModule cx md -> do
102+ traverse_ (kCTypeDefinition cx) (md ^. # typeDefs)
103+ traverse_ (kCClassInstance cx) (md ^. # instances)
104+ traverse_ (kCClass cx) (md ^. # classDefs)
105+
106+ localStrategy :: Transform ModuleCheck KindCheck
107+ localStrategy = reinterpret $ \ case
108+ KCTypeDefinition ctx tydef -> kindFromTyDef tydef >>= inferTypeKind ctx >>= checkKindConsistency tydef ctx
109+ KCClassInstance ctx instClause -> error " FIXME"
110+ KCClass ctx classDef -> error " Fixme"
111+
112+ runKindCheck :: Eff '[KindCheck ] a -> Eff '[Err ] a
113+ runKindCheck = reinterpret $ \ case
114+ KindFromTyDef tydef -> tyDef2Kind tydef
115+ InferTypeKind ctx ty -> either (\ _ -> throwError InvalidType ) pure $ infer ctx ty
116+ CheckKindConsistency def ctx k -> resolveKindConsistency def ctx k
117+
118+ runCheck :: Eff (Check ': '[] ) a -> Either KindCheckFailure a
119+ runCheck = run . runError . runKindCheck . localStrategy . moduleStrategy . globalStrategy
120+
121+ kindCheckType = undefined
122+ runKindCheckEff = undefined
123+
124+ -- Resolvers
125+
126+ resolveKindConsistency tydef ctx k = do
127+ let
128+ undefined
129+
130+ resolveCreateContext :: forall effs . P. CompilerInput -> Eff effs Context
131+ resolveCreateContext ci = mconcat <$> traverse module2Context (ci ^. # modules)
132+
133+ module2Context :: forall effs . P. Module -> Eff effs Context
134+ module2Context m = mconcat <$> traverse (tyDef2Context (flattenModuleName (m ^. # moduleName))) (P. typeDefs m)
135+ where
136+ flattenModuleName :: P. ModuleName -> Text
137+ flattenModuleName mName = intercalate " ." $ (\ p -> p ^. # name) <$> mName ^. # parts
138+
139+ type ModuleName = Text
140+
141+ tyDef2Context :: forall effs . ModuleName -> P. TyDef -> Eff effs Context
142+ tyDef2Context curModName tyDef = do
143+ let name = show $ curModName <> " ." <> (tyDef ^. # tyName . # name) -- name is qualified
144+ let ty = tyAbs2Type (tyDef ^. # tyAbs)
145+ pure $ mempty & context .~ M. singleton name ty
146+
147+ tyAbs2Type :: P. TyAbs -> Kind
148+ tyAbs2Type tyAbs = foldWithArrow $ pKind2Kind . (\ x -> x ^. # argKind) <$> (tyAbs ^. # tyArgs)
149+
150+ foldWithArrow :: [Kind ] -> Kind
151+ foldWithArrow = \ case [] -> Type ; (x : xs) -> x :->: foldWithArrow xs
152+
153+ pKind2Kind :: P. Kind -> Kind
154+ pKind2Kind k =
155+ case k ^. # kind of
156+ P. KindRef P. KType -> Type
157+ P. KindArrow l r -> pKind2Kind l :->: pKind2Kind r
158+ _ -> error " Fixme undefined type" -- FIXME what is an undefined type meant to mean?
159+
160+ tyDef2Kind = undefined
107161
108162--------------------------------------------------------------------------------
109163-- API
110-
164+ {-
111165-- | Main Kind Checking function
112- runKindCheck :: [ TyDef ] -> Either KindCheckFailure ()
166+ runKindCheck :: P.CompilerInput -> Either KindCheckFailure ()
113167runKindCheck tDefs = void $ run $ runError $ interpretKindCheck $ kindCheckDefs tDefs
168+ -}
169+
170+ -- runKindCheckEff :: Eff KindCheckEff a -> Either KindCheckFailure a
171+ -- runKindCheckEff = run . runError . interpretKindCheck
114172
115- runKindCheckEff :: Eff KindCheckEff a -> Either KindCheckFailure a
116- runKindCheckEff = run . runError . interpretKindCheck
173+ -- kindCheckType = undefined
117174
118175--------------------------------------------------------------------------------
119176-- Strategy
120-
177+ {-
121178-- | Strategy for kind checking.
122- kindCheckDefs :: [TyDef ] -> Eff KindCheckEff ()
179+ kindCheckDefs :: [PTyDef ] -> Eff KindCheckEff ()
123180kindCheckDefs tyDefs = validateInput tyDefs >>= void . kindCheckType
124181
125182kindCheckType :: [TypeDefinition] -> Eff KindCheckEff [Kind]
@@ -238,3 +295,4 @@ tyRefToType tR = do
238295 Just (TyRef'LocalTyRef t) -> pure $ Var $ t ^. tyName . name . to unpack
239296 Just (TyRef'ForeignTyRef t) -> pure $ Var $ (t ^. moduleName . parts . to (\ps -> unpack $ intercalate "." [p ^. name | p <- ps])) <> "." <> (t ^. tyName . name . to unpack)
240297 Nothing -> throwError $ InvalidProto "TyRef Cannot be empty"
298+ -}
0 commit comments