1 {-# LANGUAGE ConstraintKinds #-}
2 {-# LANGUAGE DeriveFunctor #-}
3 {-# LANGUAGE ExistentialQuantification #-}
5 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
6 {-# LANGUAGE PolyKinds #-}
7 {-# LANGUAGE UndecidableInstances #-}
8 module Language.Symantic.Compiling.Module where
10 import Data.Bool (not)
11 import Data.Map.Strict (Map)
12 import Data.Proxy (Proxy(..))
13 import Data.Semigroup (Semigroup(..))
15 import Data.String (IsString(..))
16 import Data.Text (Text)
17 import Prelude hiding (mod, not, any)
18 import qualified Data.Kind as K
19 import qualified Data.Map.Strict as Map
21 import Language.Symantic.Grammar
22 import Language.Symantic.Typing
23 import Language.Symantic.Compiling.Term
26 data Mod a = Mod PathMod a
27 deriving (Eq, Functor, Ord, Show)
30 type PathMod = [NameMod]
33 newtype NameMod = NameMod Text
34 deriving (Eq, Ord, Show)
35 instance IsString NameMod where
36 fromString = NameMod . fromString
38 -- * Class 'ModuleFor'
39 class ModuleFor src ss s where
40 moduleFor :: Proxy s -> (PathMod, Module src ss)
41 moduleFor _s = ([], moduleEmpty)
44 newtype Imports = Imports (Map PathMod (Map PathMod FilterImports))
46 type FilterImports = Maybe (Set NameTe)
48 importQualifiedAs :: PathMod -> Modules src ss -> Imports
49 importQualifiedAs as (Modules mods) = Imports $ Map.fromList [(as, Nothing <$ mods)]
52 newtype Modules src ss
54 { modules :: Map PathMod (Module src ss)
57 unionModules :: Modules src ss -> Modules src ss -> Either Error_Module (Modules src ss)
58 unionModules mx@(Modules x) my@(Modules y) =
61 Nothing -> Right $ unionModulesUnchecked mx my
64 Map PathMod (Module src ss) ->
65 Map PathMod (Module src ss) ->
68 case Map.intersectionWith (,) x' y' of
69 xy | null xy -> Nothing
72 Map.filter (not . null) $
74 inter a b module_prefix <>
75 inter a b module_infix <>
76 inter a b module_postfix in
79 e -> Just $ Error_Module_colliding_Term e
81 inter a b f = Map.keysSet $ Map.intersection (f a) (f b)
83 unionModulesUnchecked :: Modules src ss -> Modules src ss -> Modules src ss
84 unionModulesUnchecked (Modules x) (Modules y) =
85 Modules $ Map.unionWith (<>) x y
87 -- ** Type 'Error_Module'
89 = Error_Module_colliding_Term (Map PathMod (Set NameTe))
90 | Error_Module_ambiguous (Mod NameTe) (Map PathMod NameTe)
91 | Error_Module_missing PathMod
92 | Error_Module_missing_Term (Mod NameTe)
98 { module_prefix :: ModuleFixy src ss Unifix
99 , module_infix :: ModuleFixy src ss Infix
100 , module_postfix :: ModuleFixy src ss Unifix
101 } deriving (Eq, Show)
103 module_fixity :: FixitySing fixy -> Module src ss -> ModuleFixy src ss fixy
104 module_fixity = \case
105 FixitySing_Prefix -> module_prefix
106 FixitySing_Infix -> module_infix
107 FixitySing_Postfix -> module_postfix
109 moduleEmpty :: Module src ss
111 { module_prefix = mempty
112 , module_infix = mempty
113 , module_postfix = mempty
116 moduleWhere :: forall src ss. Source src => PathMod -> [DefTerm src ss] -> (PathMod, Module src ss)
117 moduleWhere mod lst =
119 { module_infix = mk $ \(n `WithFixity` fixy := t) ->
121 Fixity2 inf -> [(n, Tokenizer inf $ Token_Term . setSource (TermAVT t))]
123 , module_prefix = mk $ \(n `WithFixity` fixy := t) ->
125 Fixity1 pre@Prefix{} -> [(n, Tokenizer pre $ Token_Term . setSource (TermAVT t))]
127 , module_postfix = mk $ \(n `WithFixity` fixy := t) ->
129 Fixity1 post@Postfix{} -> [(n, Tokenizer post $ Token_Term . setSource (TermAVT t))]
134 (DefTerm src ss -> [(NameTe, Tokenizer fixy src ss)]) ->
135 Map NameTe (Tokenizer fixy src ss)
136 mk = Map.fromList . (`foldMap` lst)
138 -- *** Type 'ModuleFixy'
139 type ModuleFixy src ss fixy = Map NameTe (Tokenizer fixy src ss)
141 instance Semigroup (Module src ss) where
144 { module_prefix = module_prefix x <> module_prefix y
145 , module_infix = module_infix x <> module_infix y
146 , module_postfix = module_postfix x <> module_postfix y
149 -- ** Type 'Tokenizer'
150 data Tokenizer fixy src ss
152 { token_fixity :: fixy
153 , token_term :: src -> Token_Term src ss
155 instance (Source src, Eq fixy) => Eq (Tokenizer fixy src ss) where
156 Tokenizer fx x == Tokenizer fy y = fx == fy && (x noSource) == (y noSource)
157 instance Source src => Show (Tokenizer fixy src ss) where
158 show (Tokenizer _fx x) = show (x noSource)
160 -- ** Type 'Token_Term'
161 data Token_Term src ss
162 = Token_Term (TermAVT src ss)
163 | Token_TermVT (TermVT src ss '[])
164 | Token_Term_Abst src NameTe (AST_Type src) (AST_Term src ss)
165 | Token_Term_Var src NameTe
166 | Token_Term_Let src NameTe (AST_Term src ss) (AST_Term src ss)
168 -- deriving (Eq, Show)
169 instance Source src => Eq (Token_Term src ss) where
170 Token_Term x == Token_Term y = x == y
171 Token_TermVT x == Token_TermVT y = x == y
172 Token_Term_Abst _ nx ax rx == Token_Term_Abst _ ny ay ry = nx == ny && ax == ay && rx == ry
173 Token_Term_Var _ x == Token_Term_Var _ y = x == y
174 Token_Term_Let _ nx ax rx == Token_Term_Let _ ny ay ry = nx == ny && ax == ay && rx == ry
175 Token_Term_App _ == Token_Term_App _ = True
177 instance Source src => Show (Token_Term src ss) where
178 showsPrec p (Token_Term x) =
179 showParen (p >= 10) $
180 showString "Token_Term" .
181 showChar ' ' . showsPrec 10 x
182 showsPrec p (Token_TermVT x) =
183 showParen (p >= 10) $
184 showString "Token_TermVT" .
185 showChar ' ' . showsPrec 10 x
186 showsPrec p (Token_Term_Abst _ n a r) =
187 showParen (p >= 10) $
188 showString "Token_Term_Abst" .
189 showChar ' ' . showsPrec 10 n .
190 showChar ' ' . showsPrec 10 a .
191 showChar ' ' . showsPrec 10 r
192 showsPrec p (Token_Term_Var _ x) =
193 showParen (p >= 10) $
194 showString "Token_Term_Var" .
195 showChar ' ' . showsPrec 10 x
196 showsPrec p (Token_Term_Let _ n a r) =
197 showParen (p >= 10) $
198 showString "Token_Term_Let" .
199 showChar ' ' . showsPrec 10 n .
200 showChar ' ' . showsPrec 10 a .
201 showChar ' ' . showsPrec 10 r
202 showsPrec _p (Token_Term_App _) = showString "Token_Term_App"
205 newtype NameTe = NameTe Text
206 deriving (Eq, Ord, Show)
207 instance IsString NameTe where
208 fromString = NameTe . fromString
211 -- | /Typing context/
212 -- accumulating at each /lambda abstraction/
213 -- the 'Type' of the introduced variable.
214 -- It is built top-down from the closest
215 -- including /lambda abstraction/ to the farest.
216 data CtxTy src (ts::[K.Type]) where
217 CtxTyZ :: CtxTy src '[]
221 -> CtxTy src (t ': ts)
227 -> CtxTy src (ts0 ++ ts1)
228 appendCtxTy CtxTyZ c = c
229 appendCtxTy (CtxTyS n t c) c' = CtxTyS n t $ appendCtxTy c c'
233 -- ** Type 'AST_Term'
234 -- | /Abstract Syntax Tree/ of 'Token_Term'.
235 type AST_Term src ss = BinTree (Token_Term src ss)
237 -- * Class 'Inj_Modules'
238 type Inj_Modules src ss
239 = Inj_ModulesR src ss ss
241 inj_Modules :: forall src ss. Inj_Modules src ss => Either Error_Module (Modules src ss)
242 inj_Modules = inj_ModulesR (Proxy @ss)
244 -- ** Class 'Inj_ModulesR'
245 class Inj_ModulesR src (ss::[*]) (rs::[*]) where
246 inj_ModulesR :: Proxy rs -> Either Error_Module (Modules src ss)
247 instance Inj_ModulesR src ss '[] where
248 inj_ModulesR _rs = Right $ Modules mempty
251 , Inj_ModulesR src ss rs
252 ) => Inj_ModulesR src ss (Proxy s ': rs) where
254 x <- inj_ModulesR (Proxy @rs)
255 let (n, m) = moduleFor (Proxy @s)
256 Modules (Map.singleton n m) `unionModules` x
261 (:=) (WithFixity NameTe)
262 (forall ts. Term src ss ts vs t)
264 -- | Lookup given 'Mod' 'NameTe' into the 'Infix' 'TermDef' of given 'Modules'.
266 -- NOTE: 'Token_Term_App' is returned for the space 'NameTe'.
273 Either Error_Module (Tokenizer fixy src ss)
274 lookupDefTerm FixitySing_Infix _is ([] `Mod` " ") _ms =
276 { token_term = Token_Term_App @src @ss
277 , token_fixity = Infix (Just AssocL) 9
279 lookupDefTerm fixy (Imports is) mn@(m `Mod` n) (Modules mods) =
280 let mod_fixy = module_fixity fixy in
281 case Map.lookup m is of
283 maybe (Left $ Error_Module_missing m) Right (Map.lookup m mods) >>=
284 maybe (Left $ Error_Module_missing_Term mn) Right .
285 Map.lookup n . mod_fixy
288 -- n matches amongst ims
289 (`Map.mapMaybeWithKey` ims) $ \im _ft -> -- TODO: filter NameTe
290 Map.lookup im mods >>=
291 Map.lookup n . mod_fixy >>=
292 Just . Map.singleton n in
293 case Map.minView look of
294 Nothing -> Left $ Error_Module_missing_Term mn
295 Just (r, rs) | null rs -> Right $ snd $ Map.findMin r
296 | otherwise -> Left $ Error_Module_ambiguous mn $ fst . Map.findMin <$> look
298 -- | Delete given 'Mod' 'NameTe' into given 'Modules'.
299 deleteDefTerm :: Mod NameTe -> Modules src ss -> Modules src ss
300 deleteDefTerm (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
302 { module_prefix = Map.delete n $ module_prefix mod
303 , module_infix = Map.delete n $ module_infix mod
304 , module_postfix = Map.delete n $ module_postfix mod
307 -- | Delete given 'Mod' 'NameTe' into 'module_infix's of given 'Modules'.
308 deleteDefTermInfix :: Mod NameTe -> Modules src ss -> Modules src ss
309 deleteDefTermInfix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
310 where del mod = mod{module_infix = Map.delete n $ module_infix mod}
312 -- | Delete given 'Mod' 'NameTe' into 'module_prefix's of given 'Modules'.
313 deleteDefTermPrefix :: Mod NameTe -> Modules src ss -> Modules src ss
314 deleteDefTermPrefix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
315 where del mod = mod{module_prefix = Map.delete n $ module_prefix mod}
317 -- | Delete given 'Mod' 'NameTe' into 'module_postfix's of given 'Modules'.
318 deleteDefTermPostix :: Mod NameTe -> Modules src ss -> Modules src ss
319 deleteDefTermPostix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
320 where del mod = mod{module_postfix = Map.delete n $ module_postfix mod}
325 Mod (DefTerm src ss) -> Modules src ss -> Modules src ss
326 insertDefTerm (m `Mod` (n `WithFixity` fixy := t)) (Modules ms) =
327 Modules $ Map.insert m (insFixy fixy moduleEmpty) ms
329 insFixy :: Fixity -> Module src ss -> Module src ss
332 Fixity1 uni@Prefix{} -> mod {module_prefix = ins uni $ module_prefix mod}
333 Fixity2 inf@Infix{} -> mod {module_infix = ins inf $ module_infix mod}
334 Fixity1 uni@Postfix{} -> mod {module_postfix = ins uni $ module_postfix mod}
335 ins :: f -> ModuleFixy src ss f -> ModuleFixy src ss f
336 ins f = Map.insert n $ Tokenizer f $ Token_Term . setSource (TermAVT t)
341 Mod (TermVT src ss '[]) -> NameTe -> Fixity ->
342 Modules src ss -> Modules src ss
343 insertTermVT (m `Mod` t) n fixy (Modules ms) =
344 Modules $ Map.insert m (insFixy fixy moduleEmpty) ms
346 insFixy :: Fixity -> Module src ss -> Module src ss
349 Fixity1 uni@Prefix{} -> mod {module_prefix = ins uni $ module_prefix mod}
350 Fixity2 inf@Infix{} -> mod {module_infix = ins inf $ module_infix mod}
351 Fixity1 uni@Postfix{} -> mod {module_postfix = ins uni $ module_postfix mod}
352 ins :: f -> ModuleFixy src ss f -> ModuleFixy src ss f
353 ins f = Map.insert n $ Tokenizer f $ Token_TermVT . setSource t
355 -- ** Type 'WithFixity'
357 = WithFixity a Fixity
359 instance IsString (WithFixity NameTe) where
360 fromString a = WithFixity (fromString a) (Fixity2 infixN5)
362 withInfix :: a -> Infix -> WithFixity a
363 withInfix a inf = a `WithFixity` Fixity2 inf
364 withInfixR :: a -> Precedence -> WithFixity a
365 withInfixR a p = a `WithFixity` Fixity2 (infixR p)
366 withInfixL :: a -> Precedence -> WithFixity a
367 withInfixL a p = a `WithFixity` Fixity2 (infixL p)
368 withInfixN :: a -> Precedence -> WithFixity a
369 withInfixN a p = a `WithFixity` Fixity2 (infixN p)
370 withInfixB :: a -> (Side, Precedence) -> WithFixity a
371 withInfixB a (lr, p) = a `WithFixity` Fixity2 (infixB lr p)
372 withPrefix :: a -> Precedence -> WithFixity a
373 withPrefix a p = a `WithFixity` Fixity1 (Prefix p)
374 withPostfix :: a -> Precedence -> WithFixity a
375 withPostfix a p = a `WithFixity` Fixity1 (Postfix p)
377 -- ** Type 'FixitySing'
378 data FixitySing fixy where
379 FixitySing_Prefix :: FixitySing Unifix
380 FixitySing_Infix :: FixitySing Infix
381 FixitySing_Postfix :: FixitySing Unifix
382 deriving instance Eq (FixitySing fixy)
383 deriving instance Show (FixitySing fixy)