on 700055c help sign in
elk/src/AST/Module.hs
248 lines 4.8 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module AST.Module
4 ( Header(..), HeaderDecl(..), defaultHeaderDecl
5 , Module(..)
7 , Source, SourceInfo(..), SourceTag(..), SourceSettings, emptySettings
8 , Valid, ValidInfo(..)
9 , Canonical, Optimized, Info(..)
11 , UserImport, DefaultImport, ImportMethod(..)
13 , Types
14 , Aliases
15 , Unions, UnionInfo, CanonicalUnion
17 , Interfaces, Interface(..), toInterface, privatize
18 )
19 where
21import Data.Binary
22import qualified Data.Map as Map
23import Data.Text (Text)
25import qualified AST.Declaration as Decl
26import qualified AST.Effects as Effects
27import qualified AST.Expression.Canonical as Canonical
28import qualified AST.Expression.Optimized as Optimized
29import qualified AST.Module.Name as Name
30import qualified AST.Type as Type
31import qualified AST.Variable as Var
32import qualified Docs.AST as Docs
33import qualified Reporting.Annotation as A
34import qualified Reporting.Region as R
38-- HEADERS FOR PARSING
41{-| Basic info needed to identify modules and determine dependencies. -}
42data Header imports =
43 Header
44 { _decl :: Maybe HeaderDecl
45 , _imports :: imports
46 }
49data HeaderDecl =
50 HeaderDecl
51 { _tag :: SourceTag
52 , _name :: Name.Raw
53 , _exports :: Var.Listing (A.Located Var.Value)
54 , _settings :: SourceSettings
55 , _docs :: A.Located (Maybe Text)
56 }
59defaultHeaderDecl :: HeaderDecl
60defaultHeaderDecl =
61 let
62 zero = R.Position 1 1
63 noDocs = A.at zero zero Nothing
64 in
65 HeaderDecl Normal "Main" Var.openListing emptySettings noDocs
69-- MODULES
72data Module phase =
73 Module
74 { name :: Name.Canonical
75 , info :: phase
76 }
79type Source =
80 Module SourceInfo
83data SourceInfo =
84 Source
85 { srcTag :: SourceTag
86 , srcSettings :: SourceSettings
87 , srcDocs :: A.Located (Maybe Text)
88 , srcExports :: Var.Listing (A.Located Var.Value)
89 , srcImports :: [UserImport]
90 , srcDecls :: [Decl.Source]
91 }
94data SourceTag
95 = Normal
96 | Effect R.Region
97 | Port R.Region
100type SourceSettings =
101 A.Located [(A.Located Text, A.Located Text)]
104emptySettings :: SourceSettings
105emptySettings =
106 A.A (error "region of empty settings should not be needed") []
109type Valid =
110 Module ValidInfo
113data ValidInfo =
114 Valid
115 { validDocs :: A.Located (Maybe Text)
116 , validExports :: Var.Listing (A.Located Var.Value)
117 , validImports :: ([DefaultImport], [UserImport])
118 , validDecls :: Decl.Valid
119 , validEffects :: Effects.Raw
120 }
123type Canonical =
124 Module (Info Canonical.Expr)
127type Optimized =
128 Module (Info [Optimized.Def])
132-- IMPORTS
135type UserImport = A.Located (Name.Raw, ImportMethod)
138type DefaultImport = (Name.Raw, ImportMethod)
141data ImportMethod =
142 ImportMethod
143 { alias :: Maybe Text
144 , exposedVars :: !(Var.Listing Var.Value)
145 }
149-- LATE PHASE MODULE INFORMATION
152data Info program =
153 Info
154 { docs :: A.Located (Maybe Docs.Centralized)
155 , exports :: [Var.Value]
156 , imports :: [Name.Raw]
157 , program :: program
158 , types :: Types
159 , fixities :: [Decl.Infix]
160 , aliases :: Aliases
161 , unions :: Unions
162 , effects :: Effects.Canonical
163 }
166type Types =
167 Map.Map Text Type.Canonical
170type Aliases =
171 Map.Map Text ([Text], Type.Canonical)
174type Unions =
175 Map.Map Text (UnionInfo Text)
178type UnionInfo v =
179 ( [Text], [(v, [Type.Canonical])] )
182type CanonicalUnion =
183 ( Var.Canonical, UnionInfo Var.Canonical )
187-- INTERFACES
190type Interfaces =
191 Map.Map Name.Canonical Interface
194{-| Key facts about a module, used when reading info from .elmi files. -}
195data Interface =
196 Interface
197 { iExports :: [Var.Value]
198 , iImports :: [Name.Raw] -- TODO perhaps use this to crawl faster
199 , iTypes :: Types
200 , iUnions :: Unions
201 , iAliases :: Aliases
202 , iFixities :: [Decl.Infix]
203 }
206toInterface :: Optimized -> Interface
207toInterface modul =
208 let
209 myInfo =
210 info modul
211 in
212 Interface
213 { iExports = exports myInfo
214 , iImports = imports myInfo
215 , iTypes = types myInfo
216 , iUnions = unions myInfo
217 , iAliases = aliases myInfo
218 , iFixities = fixities myInfo
219 }
222privatize :: Interface -> Maybe Interface
223privatize (Interface _ _ _ myUnions myAliases _) =
224 if Map.null myUnions && Map.null myAliases then
225 Nothing
227 else
228 Just $ Interface
229 { iExports = []
230 , iImports = []
231 , iTypes = Map.empty
232 , iUnions = myUnions
233 , iAliases = myAliases
234 , iFixities = []
235 }
238instance Binary Interface where
239 get =
240 Interface <$> get <*> get <*> get <*> get <*> get <*> get
242 put modul =
243 do put (iExports modul)
244 put (iImports modul)
245 put (iTypes modul)
246 put (iUnions modul)
247 put (iAliases modul)
248 put (iFixities modul)