forked from elm/compiler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathArtifacts.hs
155 lines (110 loc) · 3.85 KB
/
Artifacts.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
{-# OPTIONS_GHC -Wall #-}
module Artifacts
( Artifacts(..)
, loadCompile
, loadRepl
, toDepsInfo
)
where
import Control.Concurrent (readMVar)
import Control.Monad (liftM2)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Builder as B
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Map as Map
import qualified Data.Name as N
import qualified Data.OneOrMore as OneOrMore
import qualified System.Directory as Dir
import System.FilePath ((</>))
import qualified AST.Canonical as Can
import qualified AST.Optimized as Opt
import qualified BackgroundWriter as BW
import qualified Elm.Details as Details
import qualified Elm.Interface as I
import qualified Elm.ModuleName as ModuleName
import qualified Elm.Package as Pkg
import Json.Encode ((==>))
import qualified Json.Encode as E
import qualified Json.String as Json
import qualified Reporting
-- ARTIFACTS
data Artifacts =
Artifacts
{ _ifaces :: Map.Map ModuleName.Raw I.Interface
, _graph :: Opt.GlobalGraph
}
loadCompile :: IO Artifacts
loadCompile =
load ("outlines" </> "compile")
loadRepl :: IO Artifacts
loadRepl =
load ("outlines" </> "repl")
-- LOAD
load :: FilePath -> IO Artifacts
load dir =
BW.withScope $ \scope ->
do putStrLn $ "Loading " ++ dir </> "elm.json"
style <- Reporting.terminal
root <- fmap (</> dir) Dir.getCurrentDirectory
result <- Details.load style scope root
case result of
Left _ ->
error $ "Ran into some problem loading elm.json\nTry running `elm make` in: " ++ dir
Right details ->
do omvar <- Details.loadObjects root details
imvar <- Details.loadInterfaces root details
mdeps <- readMVar imvar
mobjs <- readMVar omvar
case liftM2 (,) mdeps mobjs of
Nothing ->
error $ "Ran into some weird problem loading elm.json\nTry running `elm make` in: " ++ dir
Just (deps, objs) ->
return $ Artifacts (toInterfaces deps) objs
toInterfaces :: Map.Map ModuleName.Canonical I.DependencyInterface -> Map.Map ModuleName.Raw I.Interface
toInterfaces deps =
Map.mapMaybe toUnique $ Map.fromListWith OneOrMore.more $
Map.elems (Map.mapMaybeWithKey getPublic deps)
getPublic :: ModuleName.Canonical -> I.DependencyInterface -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore I.Interface)
getPublic (ModuleName.Canonical _ name) dep =
case dep of
I.Public iface -> Just (name, OneOrMore.one iface)
I.Private _ _ _ -> Nothing
toUnique :: OneOrMore.OneOrMore a -> Maybe a
toUnique oneOrMore =
case oneOrMore of
OneOrMore.One value -> Just value
OneOrMore.More _ _ -> Nothing
-- TO DEPS INFO
toDepsInfo :: Artifacts -> BS.ByteString
toDepsInfo (Artifacts ifaces _) =
LBS.toStrict $ B.toLazyByteString $ E.encodeUgly $ encode ifaces
-- ENCODE
encode :: Map.Map ModuleName.Raw I.Interface -> E.Value
encode ifaces =
E.dict Json.fromName encodeInterface ifaces
encodeInterface :: I.Interface -> E.Value
encodeInterface (I.Interface pkg values unions aliases binops) =
E.object
[ "pkg" ==> E.chars (Pkg.toChars pkg)
, "ops" ==> E.list E.name (Map.keys binops)
, "values" ==> E.list E.name (Map.keys values)
, "aliases" ==> E.list E.name (Map.keys (Map.filter isPublicAlias aliases))
, "types" ==> E.dict Json.fromName (E.list E.name) (Map.mapMaybe toPublicUnion unions)
]
isPublicAlias :: I.Alias -> Bool
isPublicAlias alias =
case alias of
I.PublicAlias _ -> True
I.PrivateAlias _ -> False
toPublicUnion :: I.Union -> Maybe [N.Name]
toPublicUnion union =
case union of
I.OpenUnion (Can.Union _ variants _ _) ->
Just (map getVariantName variants)
I.ClosedUnion _ ->
Just []
I.PrivateUnion _ ->
Nothing
getVariantName :: Can.Ctor -> N.Name
getVariantName (Can.Ctor name _ _ _) =
name