1 {-# LANGUAGE AllowAmbiguousTypes #-}
2 {-# LANGUAGE ConstraintKinds #-}
3 {-# LANGUAGE DeriveFunctor #-}
4 {-# LANGUAGE ExistentialQuantification #-}
6 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
7 {-# LANGUAGE PolyKinds #-}
8 {-# LANGUAGE UndecidableInstances #-}
9 module Language.Symantic.Compiling.Module where
11 import Data.Bool (not)
12 import Data.Map.Strict (Map)
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 :: (PathMod, Module src ss)
41 moduleFor = ([], 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
243 Inj_Modules src ss =>
244 Either Error_Module (Modules src ss)
245 inj_Modules = inj_ModulesR @_ @_ @ss
247 -- ** Class 'Inj_ModulesR'
248 class Inj_ModulesR src (ss::[*]) (rs::[*]) where
249 inj_ModulesR :: Either Error_Module (Modules src ss)
250 instance Inj_ModulesR src ss '[] where
251 inj_ModulesR = Right $ Modules mempty
254 , Inj_ModulesR src ss rs
255 ) => Inj_ModulesR src ss (Proxy s ': rs) where
257 x <- inj_ModulesR @_ @_ @rs
258 let (n, m) = moduleFor @_ @_ @s
259 Modules (Map.singleton n m) `unionModules` x
264 (:=) (WithFixity NameTe)
265 (forall ts. Term src ss ts vs t)
267 -- | Lookup given 'Mod' 'NameTe' into the 'Infix' 'TermDef' of given 'Modules'.
269 -- NOTE: 'Token_Term_App' is returned for the space 'NameTe'.
276 Either Error_Module (Tokenizer fixy src ss)
277 lookupDefTerm FixitySing_Infix _is ([] `Mod` " ") _ms =
279 { token_term = Token_Term_App @src @ss
280 , token_fixity = Infix (Just AssocL) 9
282 lookupDefTerm fixy (Imports is) mn@(m `Mod` n) (Modules mods) =
283 let mod_fixy = module_fixity fixy in
284 case Map.lookup m is of
286 maybe (Left $ Error_Module_missing m) Right (Map.lookup m mods) >>=
287 maybe (Left $ Error_Module_missing_Term mn) Right .
288 Map.lookup n . mod_fixy
291 -- n matches amongst ims
292 (`Map.mapMaybeWithKey` ims) $ \im _ft -> -- TODO: filter NameTe
293 Map.lookup im mods >>=
294 Map.lookup n . mod_fixy >>=
295 Just . Map.singleton n in
296 case Map.minView look of
297 Nothing -> Left $ Error_Module_missing_Term mn
298 Just (r, rs) | null rs -> Right $ snd $ Map.findMin r
299 | otherwise -> Left $ Error_Module_ambiguous mn $ fst . Map.findMin <$> look
301 -- | Delete given 'Mod' 'NameTe' into given 'Modules'.
302 deleteDefTerm :: Mod NameTe -> Modules src ss -> Modules src ss
303 deleteDefTerm (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
305 { module_prefix = Map.delete n $ module_prefix mod
306 , module_infix = Map.delete n $ module_infix mod
307 , module_postfix = Map.delete n $ module_postfix mod
310 -- | Delete given 'Mod' 'NameTe' into 'module_infix's of given 'Modules'.
311 deleteDefTermInfix :: Mod NameTe -> Modules src ss -> Modules src ss
312 deleteDefTermInfix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
313 where del mod = mod{module_infix = Map.delete n $ module_infix mod}
315 -- | Delete given 'Mod' 'NameTe' into 'module_prefix's of given 'Modules'.
316 deleteDefTermPrefix :: Mod NameTe -> Modules src ss -> Modules src ss
317 deleteDefTermPrefix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
318 where del mod = mod{module_prefix = Map.delete n $ module_prefix mod}
320 -- | Delete given 'Mod' 'NameTe' into 'module_postfix's of given 'Modules'.
321 deleteDefTermPostix :: Mod NameTe -> Modules src ss -> Modules src ss
322 deleteDefTermPostix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
323 where del mod = mod{module_postfix = Map.delete n $ module_postfix mod}
328 Mod (DefTerm src ss) -> Modules src ss -> Modules src ss
329 insertDefTerm (m `Mod` (n `WithFixity` fixy := t)) (Modules ms) =
330 Modules $ Map.insert m (insFixy fixy moduleEmpty) ms
332 insFixy :: Fixity -> Module src ss -> Module src ss
335 Fixity1 uni@Prefix{} -> mod {module_prefix = ins uni $ module_prefix mod}
336 Fixity2 inf@Infix{} -> mod {module_infix = ins inf $ module_infix mod}
337 Fixity1 uni@Postfix{} -> mod {module_postfix = ins uni $ module_postfix mod}
338 ins :: f -> ModuleFixy src ss f -> ModuleFixy src ss f
339 ins f = Map.insert n $ Tokenizer f $ Token_Term . setSource (TermAVT t)
344 Mod (TermVT src ss '[]) -> NameTe -> Fixity ->
345 Modules src ss -> Modules src ss
346 insertTermVT (m `Mod` t) n fixy (Modules ms) =
347 Modules $ Map.insert m (insFixy fixy moduleEmpty) ms
349 insFixy :: Fixity -> Module src ss -> Module src ss
352 Fixity1 uni@Prefix{} -> mod {module_prefix = ins uni $ module_prefix mod}
353 Fixity2 inf@Infix{} -> mod {module_infix = ins inf $ module_infix mod}
354 Fixity1 uni@Postfix{} -> mod {module_postfix = ins uni $ module_postfix mod}
355 ins :: f -> ModuleFixy src ss f -> ModuleFixy src ss f
356 ins f = Map.insert n $ Tokenizer f $ Token_TermVT . setSource t
358 -- ** Type 'WithFixity'
360 = WithFixity a Fixity
362 instance IsString (WithFixity NameTe) where
363 fromString a = WithFixity (fromString a) (Fixity2 infixN5)
365 withInfix :: a -> Infix -> WithFixity a
366 withInfix a inf = a `WithFixity` Fixity2 inf
367 withInfixR :: a -> Precedence -> WithFixity a
368 withInfixR a p = a `WithFixity` Fixity2 (infixR p)
369 withInfixL :: a -> Precedence -> WithFixity a
370 withInfixL a p = a `WithFixity` Fixity2 (infixL p)
371 withInfixN :: a -> Precedence -> WithFixity a
372 withInfixN a p = a `WithFixity` Fixity2 (infixN p)
373 withInfixB :: a -> (Side, Precedence) -> WithFixity a
374 withInfixB a (lr, p) = a `WithFixity` Fixity2 (infixB lr p)
375 withPrefix :: a -> Precedence -> WithFixity a
376 withPrefix a p = a `WithFixity` Fixity1 (Prefix p)
377 withPostfix :: a -> Precedence -> WithFixity a
378 withPostfix a p = a `WithFixity` Fixity1 (Postfix p)
380 -- ** Type 'FixitySing'
381 data FixitySing fixy where
382 FixitySing_Prefix :: FixitySing Unifix
383 FixitySing_Infix :: FixitySing Infix
384 FixitySing_Postfix :: FixitySing Unifix
385 deriving instance Eq (FixitySing fixy)
386 deriving instance Show (FixitySing fixy)