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))
45 type FilterImports = Maybe (Set NameTe)
47 importModulesAs :: PathMod -> Modules src ss -> Imports
48 importModulesAs as (Modules mods) = Imports $ Map.fromList [(as, Nothing <$ mods)]
51 newtype Modules src ss
53 { modules :: Map PathMod (Module src ss)
56 unionModules :: Modules src ss -> Modules src ss -> Either Error_Module (Modules src ss)
57 unionModules mx@(Modules x) my@(Modules y) =
60 Nothing -> Right $ unionModulesUnchecked mx my
63 Map PathMod (Module src ss) ->
64 Map PathMod (Module src ss) ->
67 case Map.intersectionWith (,) x' y' of
68 xy | null xy -> Nothing
71 Map.filter (not . null) $
73 inter a b module_prefix <>
74 inter a b module_infix <>
75 inter a b module_postfix in
78 e -> Just $ Error_Module_colliding_Term e
80 inter a b f = Map.keysSet $ Map.intersection (f a) (f b)
82 unionModulesUnchecked :: Modules src ss -> Modules src ss -> Modules src ss
83 unionModulesUnchecked (Modules x) (Modules y) =
84 Modules $ Map.unionWith (<>) x y
86 -- ** Type 'Error_Module'
88 = Error_Module_colliding_Term (Map PathMod (Set NameTe))
89 | Error_Module_ambiguous (Mod NameTe) (Map PathMod NameTe)
90 | Error_Module_missing PathMod
91 | Error_Module_missing_Term (Mod NameTe)
97 { module_prefix :: ModuleFixy src ss Unifix
98 , module_infix :: ModuleFixy src ss Infix
99 , module_postfix :: ModuleFixy src ss Unifix
100 } deriving (Eq, Show)
102 module_fixity :: FixitySing fixy -> Module src ss -> ModuleFixy src ss fixy
103 module_fixity = \case
104 FixitySing_Prefix -> module_prefix
105 FixitySing_Infix -> module_infix
106 FixitySing_Postfix -> module_postfix
108 moduleEmpty :: Module src ss
110 { module_prefix = mempty
111 , module_infix = mempty
112 , module_postfix = mempty
115 moduleWhere :: forall src ss. Source src => PathMod -> [DefTerm src ss] -> (PathMod, Module src ss)
116 moduleWhere mod lst =
118 { module_infix = mk $ \(n `WithFixity` fixy := t) ->
120 Fixity2 inf -> [(n, Tokenizer inf $ Token_Term . setSource (TermAVT t))]
122 , module_prefix = mk $ \(n `WithFixity` fixy := t) ->
124 Fixity1 pre@Prefix{} -> [(n, Tokenizer pre $ Token_Term . setSource (TermAVT t))]
126 , module_postfix = mk $ \(n `WithFixity` fixy := t) ->
128 Fixity1 post@Postfix{} -> [(n, Tokenizer post $ Token_Term . setSource (TermAVT t))]
133 (DefTerm src ss -> [(NameTe, Tokenizer fixy src ss)]) ->
134 Map NameTe (Tokenizer fixy src ss)
135 mk = Map.fromList . (`foldMap` lst)
137 -- *** Type 'ModuleFixy'
138 type ModuleFixy src ss fixy = Map NameTe (Tokenizer fixy src ss)
140 instance Semigroup (Module src ss) where
143 { module_prefix = module_prefix x <> module_prefix y
144 , module_infix = module_infix x <> module_infix y
145 , module_postfix = module_postfix x <> module_postfix y
148 -- ** Type 'Tokenizer'
149 data Tokenizer fixy src ss
151 { token_fixity :: fixy
152 , token_term :: src -> Token_Term src ss
154 instance (Source src, Eq fixy) => Eq (Tokenizer fixy src ss) where
155 Tokenizer fx x == Tokenizer fy y = fx == fy && (x noSource) == (y noSource)
156 instance Source src => Show (Tokenizer fixy src ss) where
157 show (Tokenizer _fx x) = show (x noSource)
159 -- ** Type 'Token_Term'
160 data Token_Term src ss
161 = Token_Term (TermAVT src ss)
162 | Token_TermVT (TermVT src ss '[])
163 | Token_Term_Abst src NameTe (AST_Type src) (AST_Term src ss)
164 | Token_Term_Var src NameTe
165 | Token_Term_Let src NameTe (AST_Term src ss) (AST_Term src ss)
167 -- deriving (Eq, Show)
168 instance Source src => Eq (Token_Term src ss) where
169 Token_Term x == Token_Term y = x == y
170 Token_TermVT x == Token_TermVT y = x == y
171 Token_Term_Abst _ nx ax rx == Token_Term_Abst _ ny ay ry = nx == ny && ax == ay && rx == ry
172 Token_Term_Var _ x == Token_Term_Var _ y = x == y
173 Token_Term_Let _ nx ax rx == Token_Term_Let _ ny ay ry = nx == ny && ax == ay && rx == ry
174 Token_Term_App _ == Token_Term_App _ = True
176 instance Source src => Show (Token_Term src ss) where
177 showsPrec p (Token_Term x) =
178 showParen (p >= 10) $
179 showString "Token_Term" .
180 showChar ' ' . showsPrec 10 x
181 showsPrec p (Token_TermVT x) =
182 showParen (p >= 10) $
183 showString "Token_TermVT" .
184 showChar ' ' . showsPrec 10 x
185 showsPrec p (Token_Term_Abst _ n a r) =
186 showParen (p >= 10) $
187 showString "Token_Term_Abst" .
188 showChar ' ' . showsPrec 10 n .
189 showChar ' ' . showsPrec 10 a .
190 showChar ' ' . showsPrec 10 r
191 showsPrec p (Token_Term_Var _ x) =
192 showParen (p >= 10) $
193 showString "Token_Term_Var" .
194 showChar ' ' . showsPrec 10 x
195 showsPrec p (Token_Term_Let _ n a r) =
196 showParen (p >= 10) $
197 showString "Token_Term_Let" .
198 showChar ' ' . showsPrec 10 n .
199 showChar ' ' . showsPrec 10 a .
200 showChar ' ' . showsPrec 10 r
201 showsPrec _p (Token_Term_App _) = showString "Token_Term_App"
204 newtype NameTe = NameTe Text
205 deriving (Eq, Ord, Show)
206 instance IsString NameTe where
207 fromString = NameTe . fromString
210 -- | /Typing context/
211 -- accumulating at each /lambda abstraction/
212 -- the 'Type' of the introduced variable.
213 -- It is built top-down from the closest
214 -- including /lambda abstraction/ to the farest.
215 data CtxTy src (ts::[K.Type]) where
216 CtxTyZ :: CtxTy src '[]
220 -> CtxTy src (t ': ts)
226 -> CtxTy src (ts0 ++ ts1)
227 appendCtxTy CtxTyZ c = c
228 appendCtxTy (CtxTyS n t c) c' = CtxTyS n t $ appendCtxTy c c'
232 -- ** Type 'AST_Term'
233 -- | /Abstract Syntax Tree/ of 'Token_Term'.
234 type AST_Term src ss = BinTree (Token_Term src ss)
236 -- * Class 'Inj_Modules'
237 type Inj_Modules src ss
238 = Inj_ModulesR src ss ss
240 inj_Modules :: forall src ss. Inj_Modules src ss => Either Error_Module (Modules src ss)
241 inj_Modules = inj_ModulesR (Proxy @ss)
243 -- ** Class 'Inj_ModulesR'
244 class Inj_ModulesR src (ss::[*]) (rs::[*]) where
245 inj_ModulesR :: Proxy rs -> Either Error_Module (Modules src ss)
246 instance Inj_ModulesR src ss '[] where
247 inj_ModulesR _rs = Right $ Modules mempty
250 , Inj_ModulesR src ss rs
251 ) => Inj_ModulesR src ss (Proxy s ': rs) where
253 x <- inj_ModulesR (Proxy @rs)
254 let (n, m) = moduleFor (Proxy @s)
255 Modules (Map.singleton n m) `unionModules` x
260 (:=) (WithFixity NameTe)
261 (forall ts. Term src ss ts vs t)
263 -- | Lookup given 'Mod' 'NameTe' into the 'Infix' 'TermDef' of given 'Modules'.
265 -- NOTE: 'Token_Term_App' is returned for the space 'NameTe'.
272 Either Error_Module (Tokenizer fixy src ss)
273 lookupDefTerm FixitySing_Infix _is ([] `Mod` " ") _ms =
275 { token_term = Token_Term_App @src @ss
276 , token_fixity = Infix (Just AssocL) 9
278 lookupDefTerm fixy (Imports is) mn@(m `Mod` n) (Modules mods) =
279 let mod_fixy = module_fixity fixy in
280 case Map.lookup m is of
282 maybe (Left $ Error_Module_missing m) Right (Map.lookup m mods) >>=
283 maybe (Left $ Error_Module_missing_Term mn) Right .
284 Map.lookup n . mod_fixy
287 -- n matches amongst ims
288 (`Map.mapMaybeWithKey` ims) $ \im _ft -> -- TODO: filter NameTe
289 Map.lookup im mods >>=
290 Map.lookup n . mod_fixy >>=
291 Just . Map.singleton n in
292 case Map.minView look of
293 Nothing -> Left $ Error_Module_missing_Term mn
294 Just (r, rs) | null rs -> Right $ snd $ Map.findMin r
295 | otherwise -> Left $ Error_Module_ambiguous mn $ fst . Map.findMin <$> look
297 -- | Delete given 'Mod' 'NameTe' into given 'Modules'.
298 deleteDefTerm :: Mod NameTe -> Modules src ss -> Modules src ss
299 deleteDefTerm (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
301 { module_prefix = Map.delete n $ module_prefix mod
302 , module_infix = Map.delete n $ module_infix mod
303 , module_postfix = Map.delete n $ module_postfix mod
306 -- | Delete given 'Mod' 'NameTe' into 'module_infix's of given 'Modules'.
307 deleteDefTermInfix :: Mod NameTe -> Modules src ss -> Modules src ss
308 deleteDefTermInfix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
309 where del mod = mod{module_infix = Map.delete n $ module_infix mod}
311 -- | Delete given 'Mod' 'NameTe' into 'module_prefix's of given 'Modules'.
312 deleteDefTermPrefix :: Mod NameTe -> Modules src ss -> Modules src ss
313 deleteDefTermPrefix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
314 where del mod = mod{module_prefix = Map.delete n $ module_prefix mod}
316 -- | Delete given 'Mod' 'NameTe' into 'module_postfix's of given 'Modules'.
317 deleteDefTermPostix :: Mod NameTe -> Modules src ss -> Modules src ss
318 deleteDefTermPostix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
319 where del mod = mod{module_postfix = Map.delete n $ module_postfix mod}
324 Mod (DefTerm src ss) -> Modules src ss -> Modules src ss
325 insertDefTerm (m `Mod` (n `WithFixity` fixy := t)) (Modules ms) =
326 Modules $ Map.insert m (insFixy fixy moduleEmpty) ms
328 insFixy :: Fixity -> Module src ss -> Module src ss
331 Fixity1 uni@Prefix{} -> mod {module_prefix = ins uni $ module_prefix mod}
332 Fixity2 inf@Infix{} -> mod {module_infix = ins inf $ module_infix mod}
333 Fixity1 uni@Postfix{} -> mod {module_postfix = ins uni $ module_postfix mod}
334 ins :: f -> ModuleFixy src ss f -> ModuleFixy src ss f
335 ins f = Map.insert n $ Tokenizer f $ Token_Term . setSource (TermAVT t)
340 Mod (TermVT src ss '[]) -> NameTe -> Fixity ->
341 Modules src ss -> Modules src ss
342 insertTermVT (m `Mod` t) n fixy (Modules ms) =
343 Modules $ Map.insert m (insFixy fixy moduleEmpty) ms
345 insFixy :: Fixity -> Module src ss -> Module src ss
348 Fixity1 uni@Prefix{} -> mod {module_prefix = ins uni $ module_prefix mod}
349 Fixity2 inf@Infix{} -> mod {module_infix = ins inf $ module_infix mod}
350 Fixity1 uni@Postfix{} -> mod {module_postfix = ins uni $ module_postfix mod}
351 ins :: f -> ModuleFixy src ss f -> ModuleFixy src ss f
352 ins f = Map.insert n $ Tokenizer f $ Token_TermVT . setSource t
354 -- ** Type 'WithFixity'
356 = WithFixity a Fixity
358 instance IsString (WithFixity NameTe) where
359 fromString a = WithFixity (fromString a) (Fixity2 infixN5)
361 withInfix :: a -> Infix -> WithFixity a
362 withInfix a inf = a `WithFixity` Fixity2 inf
363 withInfixR :: a -> Precedence -> WithFixity a
364 withInfixR a p = a `WithFixity` Fixity2 (infixR p)
365 withInfixL :: a -> Precedence -> WithFixity a
366 withInfixL a p = a `WithFixity` Fixity2 (infixL p)
367 withInfixN :: a -> Precedence -> WithFixity a
368 withInfixN a p = a `WithFixity` Fixity2 (infixN p)
369 withInfixB :: a -> (Side, Precedence) -> WithFixity a
370 withInfixB a (lr, p) = a `WithFixity` Fixity2 (infixB lr p)
371 withPrefix :: a -> Precedence -> WithFixity a
372 withPrefix a p = a `WithFixity` Fixity1 (Prefix p)
373 withPostfix :: a -> Precedence -> WithFixity a
374 withPostfix a p = a `WithFixity` Fixity1 (Postfix p)
376 -- ** Type 'FixitySing'
377 data FixitySing fixy where
378 FixitySing_Prefix :: FixitySing Unifix
379 FixitySing_Infix :: FixitySing Infix
380 FixitySing_Postfix :: FixitySing Unifix
381 deriving instance Eq (FixitySing fixy)
382 deriving instance Show (FixitySing fixy)