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.Map.Strict as Map
20 import Language.Symantic.Grammar
21 import Language.Symantic.Typing
22 import Language.Symantic.Compiling.Term
25 data Mod a = Mod PathMod a
26 deriving (Eq, Functor, Ord, Show)
29 type PathMod = [NameMod]
32 newtype NameMod = NameMod Text
33 deriving (Eq, Ord, Show)
34 instance IsString NameMod where
35 fromString = NameMod . fromString
38 newtype NameTe = NameTe Text
39 deriving (Eq, Ord, Show)
40 instance IsString NameTe where
41 fromString = NameTe . fromString
43 -- * Class 'ModuleFor'
44 class ModuleFor src ss s where
45 moduleFor :: Proxy s -> (PathMod, Module src ss)
46 moduleFor _s = ([], moduleEmpty)
49 newtype Imports = Imports (Map PathMod (Map PathMod FilterImports))
50 type FilterImports = Maybe (Set NameTe)
52 importModulesAs :: PathMod -> Modules src ss -> Imports
53 importModulesAs as (Modules mods) = Imports $ Map.fromList [(as, Nothing <$ mods)]
56 newtype Modules src ss
58 { modules :: Map PathMod (Module src ss)
61 unionModules :: Modules src ss -> Modules src ss -> Either Error_Module (Modules src ss)
62 unionModules mx@(Modules x) my@(Modules y) =
65 Nothing -> Right $ unionModulesUnchecked mx my
68 Map PathMod (Module src ss) ->
69 Map PathMod (Module src ss) ->
72 case Map.intersectionWith (,) x' y' of
73 xy | null xy -> Nothing
76 Map.filter (not . null) $
78 inter a b module_prefix <>
79 inter a b module_infix <>
80 inter a b module_postfix in
83 e -> Just $ Error_Module_colliding_Term e
85 inter a b f = Map.keysSet $ Map.intersection (f a) (f b)
87 unionModulesUnchecked :: Modules src ss -> Modules src ss -> Modules src ss
88 unionModulesUnchecked (Modules x) (Modules y) =
89 Modules $ Map.unionWith (<>) x y
91 -- ** Type 'Error_Module'
93 = Error_Module_colliding_Term (Map PathMod (Set NameTe))
94 | Error_Module_ambiguous (Mod NameTe) (Map PathMod NameTe)
95 | Error_Module_missing PathMod
96 | Error_Module_missing_Term (Mod NameTe)
102 { module_prefix :: ModuleFixy src ss Unifix
103 , module_infix :: ModuleFixy src ss Infix
104 , module_postfix :: ModuleFixy src ss Unifix
107 module_fixity :: FixitySing fixy -> Module src ss -> ModuleFixy src ss fixy
108 module_fixity = \case
109 FixitySing_Prefix -> module_prefix
110 FixitySing_Infix -> module_infix
111 FixitySing_Postfix -> module_postfix
113 moduleEmpty :: Module src ss
115 { module_prefix = mempty
116 , module_infix = mempty
117 , module_postfix = mempty
120 moduleWhere :: forall src ss. Source src => PathMod -> [DefTerm src ss] -> (PathMod, Module src ss)
121 moduleWhere mod lst =
123 { module_infix = mk $ \(n `WithFixity` fixy := t) ->
125 Fixity2 inf -> [(n, Tokenizer inf $ Token_Term . setSource (TermVT_CF t))]
127 , module_prefix = mk $ \(n `WithFixity` fixy := t) ->
129 Fixity1 pre@Prefix{} -> [(n, Tokenizer pre $ Token_Term . setSource (TermVT_CF t))]
131 , module_postfix = mk $ \(n `WithFixity` fixy := t) ->
133 Fixity1 post@Postfix{} -> [(n, Tokenizer post $ Token_Term . setSource (TermVT_CF t))]
138 (DefTerm src ss -> [(NameTe, Tokenizer fixy src ss)]) ->
139 Map NameTe (Tokenizer fixy src ss)
140 mk = Map.fromList . (`foldMap` lst)
142 -- *** Type 'ModuleFixy'
143 type ModuleFixy src ss fixy = Map NameTe (Tokenizer fixy src ss)
146 ( Show (Tokenizer Unifix src ss)
147 , Show (Tokenizer Infix src ss)
148 ) => Show (Module src ss)
149 instance Semigroup (Module src ss) where
152 { module_prefix = module_prefix x <> module_prefix y
153 , module_infix = module_infix x <> module_infix y
154 , module_postfix = module_postfix x <> module_postfix y
157 -- ** Type 'Tokenizer'
158 data Tokenizer fixy src ss
160 { token_fixity :: fixy
161 , token_term :: src -> Token_Term src ss
164 -- ** Type 'Token_Term'
165 data Token_Term src ss
166 = Token_Term (TermVT_CF src ss)
167 | Token_Term_Abst src NameTe (AST_Type src) (AST_Term src ss)
168 | Token_Term_Var src NameTe
169 | Token_Term_Let src NameTe (AST_Term src ss) (AST_Term src ss)
173 -- ** Type 'AST_Term'
174 -- | /Abstract Syntax Tree/ of 'Token_Term'.
175 type AST_Term src ss = BinTree (Token_Term src ss)
177 -- * Class 'Inj_Modules'
178 type Inj_Modules src ss
179 = Inj_ModulesR src ss ss
181 inj_Modules :: forall src ss. Inj_Modules src ss => Either Error_Module (Modules src ss)
182 inj_Modules = inj_ModulesR (Proxy @ss)
184 -- ** Class 'Inj_ModulesR'
185 class Inj_ModulesR src (ss::[*]) (rs::[*]) where
186 inj_ModulesR :: Proxy rs -> Either Error_Module (Modules src ss)
187 instance Inj_ModulesR src ss '[] where
188 inj_ModulesR _rs = Right $ Modules mempty
191 , Inj_ModulesR src ss rs
192 ) => Inj_ModulesR src ss (Proxy s ': rs) where
194 x <- inj_ModulesR (Proxy @rs)
195 let (n, m) = moduleFor (Proxy @s)
196 Modules (Map.singleton n m) `unionModules` x
201 (:=) (WithFixity NameTe)
202 (forall es. Term src ss es vs t)
204 -- | Lookup given 'Mod' 'NameTe' into the 'Infix' 'TermDef' of given 'Modules'.
206 -- NOTE: 'Token_Term_App' is returned for the space 'NameTe'.
213 Either Error_Module (Tokenizer fixy src ss)
214 lookupDefTerm FixitySing_Infix _is ([] `Mod` " ") _ms =
216 { token_term = Token_Term_App @src @ss
217 , token_fixity = Infix (Just AssocL) 9
219 lookupDefTerm fixy (Imports is) mn@(m `Mod` n) (Modules mods) =
220 let mod_fixy = module_fixity fixy in
221 case Map.lookup m is of
223 maybe (Left $ Error_Module_missing m) Right (Map.lookup m mods) >>=
224 maybe (Left $ Error_Module_missing_Term mn) Right .
225 Map.lookup n . mod_fixy
228 -- n matches amongst ims
229 (`Map.mapMaybeWithKey` ims) $ \im _ft -> -- TODO: filter NameTe
230 Map.lookup im mods >>=
231 Map.lookup n . mod_fixy >>=
232 Just . Map.singleton n in
233 case Map.minView look of
234 Nothing -> Left $ Error_Module_missing_Term mn
235 Just (r, rs) | null rs -> Right $ snd $ Map.findMin r
236 | otherwise -> Left $ Error_Module_ambiguous mn $ fst . Map.findMin <$> look
238 -- | Delete given 'Mod' 'NameTe' into given 'Modules'.
239 deleteDefTerm :: Mod NameTe -> Modules src ss -> Modules src ss
240 deleteDefTerm (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
242 { module_prefix = Map.delete n $ module_prefix mod
243 , module_infix = Map.delete n $ module_infix mod
244 , module_postfix = Map.delete n $ module_postfix mod
247 -- | Delete given 'Mod' 'NameTe' into 'module_infix's of given 'Modules'.
248 deleteDefTermInfix :: Mod NameTe -> Modules src ss -> Modules src ss
249 deleteDefTermInfix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
250 where del mod = mod{module_infix = Map.delete n $ module_infix mod}
252 -- | Delete given 'Mod' 'NameTe' into 'module_prefix's of given 'Modules'.
253 deleteDefTermPrefix :: Mod NameTe -> Modules src ss -> Modules src ss
254 deleteDefTermPrefix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
255 where del mod = mod{module_prefix = Map.delete n $ module_prefix mod}
257 -- | Delete given 'Mod' 'NameTe' into 'module_postfix's of given 'Modules'.
258 deleteDefTermPostix :: Mod NameTe -> Modules src ss -> Modules src ss
259 deleteDefTermPostix (m `Mod` n) (Modules ms) = Modules $ Map.adjust del m ms
260 where del mod = mod{module_postfix = Map.delete n $ module_postfix mod}
265 Mod (DefTerm src ss) -> Modules src ss -> Modules src ss
266 insertDefTerm (m `Mod` (n `WithFixity` fixy := t)) (Modules ms) =
267 Modules $ Map.insert m (insFixy fixy moduleEmpty) ms
269 insFixy :: Fixity -> Module src ss -> Module src ss
272 Fixity1 uni@Prefix{} -> mod {module_prefix = ins uni $ module_prefix mod}
273 Fixity2 inf@Infix{} -> mod {module_infix = ins inf $ module_infix mod}
274 Fixity1 uni@Postfix{} -> mod {module_postfix = ins uni $ module_postfix mod}
275 ins :: f -> ModuleFixy src ss f -> ModuleFixy src ss f
276 ins f = Map.insert n $ Tokenizer f $ Token_Term . setSource (TermVT_CF t)
278 -- ** Type 'WithFixity'
280 = WithFixity a Fixity
282 instance IsString (WithFixity NameTe) where
283 fromString a = WithFixity (fromString a) (Fixity2 infixN5)
285 withInfix :: a -> Infix -> WithFixity a
286 withInfix a inf = a `WithFixity` Fixity2 inf
287 withInfixR :: a -> Precedence -> WithFixity a
288 withInfixR a p = a `WithFixity` Fixity2 (infixR p)
289 withInfixL :: a -> Precedence -> WithFixity a
290 withInfixL a p = a `WithFixity` Fixity2 (infixL p)
291 withInfixN :: a -> Precedence -> WithFixity a
292 withInfixN a p = a `WithFixity` Fixity2 (infixN p)
293 withInfixB :: a -> (Side, Precedence) -> WithFixity a
294 withInfixB a (lr, p) = a `WithFixity` Fixity2 (infixB lr p)
295 withPrefix :: a -> Precedence -> WithFixity a
296 withPrefix a p = a `WithFixity` Fixity1 (Prefix p)
297 withPostfix :: a -> Precedence -> WithFixity a
298 withPostfix a p = a `WithFixity` Fixity1 (Postfix p)
300 -- ** Type 'FixitySing'
301 data FixitySing fixy where
302 FixitySing_Prefix :: FixitySing Unifix
303 FixitySing_Infix :: FixitySing Infix
304 FixitySing_Postfix :: FixitySing Unifix
305 deriving instance Eq (FixitySing fixy)
306 deriving instance Show (FixitySing fixy)