on 357b7e4 help sign in
elk/src/AST/Module.hs
242 lines 4.8 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module AST.Module
4 ( Header(..), defaultHeader, Module(..)
6 , Source, SourceInfo(..), SourceTag(..), SourceSettings, emptySettings
7 , Valid, ValidInfo(..)
8 , Canonical, Optimized, Info(..)
10 , UserImport, DefaultImport, ImportMethod(..)
12 , Types
13 , Aliases
14 , Unions, UnionInfo, CanonicalUnion
16 , Interfaces, Interface(..), toInterface, privatize
17 )
18 where
20import Data.Binary
21import qualified Data.Map as Map
22import Data.Text (Text)
24import qualified AST.Declaration as Decl
25import qualified AST.Effects as Effects
26import qualified AST.Expression.Canonical as Canonical
27import qualified AST.Expression.Optimized as Optimized
28import qualified AST.Module.Name as Name
29import qualified AST.Type as Type
30import qualified AST.Variable as Var
31import qualified Docs.AST as Docs
32import qualified Reporting.Annotation as A
33import qualified Reporting.Region as R
37-- HEADERS FOR PARSING
40{-| Basic info needed to identify modules and determine dependencies. -}
41data Header imports =
42 Header
43 { _tag :: SourceTag
44 , _name :: Name.Raw
45 , _exports :: Var.Listing (A.Located Var.Value)
46 , _settings :: SourceSettings
47 , _docs :: A.Located (Maybe Text)
48 , _imports :: imports
49 }
52instance Show (Header a) where
53 show header =
54 show (_name header)
57defaultHeader :: R.Position -> R.Position -> imports -> Header imports
58defaultHeader start end imports_ =
59 Header Normal "Main" Var.openListing emptySettings (A.at start end Nothing) imports_
63-- MODULES
66data Module phase =
67 Module
68 { name :: Name.Canonical
69 , info :: phase
70 }
73type Source =
74 Module SourceInfo
77data SourceInfo =
78 Source
79 { srcTag :: SourceTag
80 , srcSettings :: SourceSettings
81 , srcDocs :: A.Located (Maybe Text)
82 , srcExports :: Var.Listing (A.Located Var.Value)
83 , srcImports :: [UserImport]
84 , srcDecls :: [Decl.Source]
85 }
88data SourceTag
89 = Normal
90 | Effect R.Region
91 | Port R.Region
94type SourceSettings =
95 A.Located [(A.Located Text, A.Located Text)]
98emptySettings :: SourceSettings
99emptySettings =
100 A.A (error "region of empty settings should not be needed") []
103type Valid =
104 Module ValidInfo
107data ValidInfo =
108 Valid
109 { validDocs :: A.Located (Maybe Text)
110 , validExports :: Var.Listing (A.Located Var.Value)
111 , validImports :: ([DefaultImport], [UserImport])
112 , validDecls :: Decl.Valid
113 , validEffects :: Effects.Raw
114 }
117type Canonical =
118 Module (Info Canonical.Expr)
121type Optimized =
122 Module (Info [Optimized.Def])
126-- IMPORTS
129type UserImport = A.Located (Name.Raw, ImportMethod)
132type DefaultImport = (Name.Raw, ImportMethod)
135data ImportMethod =
136 ImportMethod
137 { alias :: Maybe Text
138 , exposedVars :: !(Var.Listing Var.Value)
139 }
143-- LATE PHASE MODULE INFORMATION
146data Info program =
147 Info
148 { docs :: A.Located (Maybe Docs.Centralized)
149 , exports :: [Var.Value]
150 , imports :: [Name.Raw]
151 , program :: program
152 , types :: Types
153 , fixities :: [Decl.Infix]
154 , aliases :: Aliases
155 , unions :: Unions
156 , effects :: Effects.Canonical
157 }
160type Types =
161 Map.Map Text Type.Canonical
164type Aliases =
165 Map.Map Text ([Text], Type.Canonical)
168type Unions =
169 Map.Map Text (UnionInfo Text)
172type UnionInfo v =
173 ( [Text], [(v, [Type.Canonical])] )
176type CanonicalUnion =
177 ( Var.Canonical, UnionInfo Var.Canonical )
181-- INTERFACES
184type Interfaces =
185 Map.Map Name.Canonical Interface
188{-| Key facts about a module, used when reading info from .elmi files. -}
189data Interface =
190 Interface
191 { iExports :: [Var.Value]
192 , iImports :: [Name.Raw] -- TODO perhaps use this to crawl faster
193 , iTypes :: Types
194 , iUnions :: Unions
195 , iAliases :: Aliases
196 , iFixities :: [Decl.Infix]
197 }
200toInterface :: Optimized -> Interface
201toInterface modul =
202 let
203 myInfo =
204 info modul
205 in
206 Interface
207 { iExports = exports myInfo
208 , iImports = imports myInfo
209 , iTypes = types myInfo
210 , iUnions = unions myInfo
211 , iAliases = aliases myInfo
212 , iFixities = fixities myInfo
213 }
216privatize :: Interface -> Maybe Interface
217privatize (Interface _ _ _ myUnions myAliases _) =
218 if Map.null myUnions && Map.null myAliases then
219 Nothing
221 else
222 Just $ Interface
223 { iExports = []
224 , iImports = []
225 , iTypes = Map.empty
226 , iUnions = myUnions
227 , iAliases = myAliases
228 , iFixities = []
229 }
232instance Binary Interface where
233 get =
234 Interface <$> get <*> get <*> get <*> get <*> get <*> get
236 put modul =
237 do put (iExports modul)
238 put (iImports modul)
239 put (iTypes modul)
240 put (iUnions modul)
241 put (iAliases modul)
242 put (iFixities modul)