@@ -1,158 +1,242 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE Rank2Types #-}
3module Elm.Compiler.Type.Extract
4module Elm.Compiler.Type.Extract
4− ( extract
5+ ( fromAnnotation
5− , extractProgram
6+ , fromType
9−import qualified Control.Monad.Writer.Strict as Writer
11+
10import qualified Data.Map as Map
13import qualified Data.Map as Map
11import qualified Data.Maybe as Maybe
14import qualified Data.Maybe as Maybe
15+import Data.Monoid ((<>))
12import qualified Data.Set as Set
16import qualified Data.Set as Set
13−import Data.Text (Text)
15−import qualified AST.Module as Module
18+import qualified AST.Canonical as Can
19+import qualified AST.Optimized as Opt
16import qualified AST.Module.Name as ModuleName
20import qualified AST.Module.Name as ModuleName
17−import qualified AST.Type as T
21+import qualified AST.Utils.Type as Type
22+import qualified Elm.Compiler.Type as T
18−import qualified AST.Variable as Var
23+import qualified Elm.Interface as I
19−import Elm.Compiler.Type (Type(..), Program(Program))
24+import qualified Elm.Name as N
23-- EXTRACTION
28-- EXTRACTION
26−extract :: T.Canonical -> Type
31+fromAnnotation :: Can.Annotation -> T.Type
27−extract astType =
32+fromAnnotation (Can.Forall _ astType) =
28− fst $ Writer.runWriter $ extractHelp astType
33+ fromType astType
31−type Deps =
36+fromType :: Can.Type -> T.Type
32− ( Set.Set Var.Canonical -- aliases
37+fromType astType =
33− , Set.Set Var.Canonical -- unions
38+ snd (run (extract astType))
37−diff :: Deps -> Deps -> Deps
41+extract :: Can.Type -> Extractor T.Type
38−diff (oldAliases, oldUnions) (newAliases, newUnions) =
42+extract astType =
39− ( Set.difference newAliases oldAliases
43+ case astType of
40− , Set.difference newUnions oldUnions
44+ Can.TLambda arg result ->
44−extractHelp :: T.Canonical -> Writer.Writer Deps Type
52+ Can.TType home name args ->
45−extractHelp astType =
53+ addUnion (Opt.Global home name) (T.Type (toPublicName home name))
46− case astType of
54+ <*> traverse extract args
47− T.Lambda arg result ->
55+
48− Lambda <$> extractHelp arg <*> extractHelp result
56+ Can.TRecord fields ext ->
58+ <$> fmap Map.toList (traverse extract fields)
59+ <*> traverse extract ext
50− T.Var x ->
61+ Can.TUnit ->
51− return (Var x)
62+ pure T.Unit
53− T.Type var args ->
64+ Can.TTuple a b maybeC ->
54− do Writer.tell ( Set.empty, Set.singleton var )
65+ T.Tuple
55− Type (Var.toText var) <$> traverse extractHelp args
66+ <$> extract a
68+ <*> traverse extract (Maybe.maybeToList maybeC)
57− T.Record fields ext ->
70+ Can.TAlias home name args aliasType ->
58− Record
71+ do addAlias (Opt.Global home name) ()
59− <$> traverse (traverse extractHelp) fields
72+ _ <- extract (Type.dealias args aliasType)
60− <*> traverse extractHelp ext
73+ T.Type (toPublicName home name)
74+ <$> traverse (extract . snd) args
62− T.Aliased name args aliasedType ->
76+
63− do Writer.tell ( Set.singleton name, Set.empty )
77+toPublicName :: ModuleName.Canonical -> N.Name -> N.Name
64− _ <- extractHelp (T.dealias args aliasedType)
78+toPublicName (ModuleName.Canonical _ home) name =
65− Type (Var.toText name) <$> traverse (extractHelp . snd) args
79+ home <> "." <> name
69-- EXTRACT MODEL, MSG, AND ANY TRANSITIVE DEPENDENCIES
83-- EXTRACT MODEL, MSG, AND ANY TRANSITIVE DEPENDENCIES
72−extractProgram :: Module.Interfaces -> ModuleName.Canonical -> Maybe Program
86+fromProgram :: I.Interfaces -> ModuleName.Canonical -> Maybe T.Program
73−extractProgram interfaces name =
87+fromProgram interfaces name =
74 do iface <- Map.lookup name interfaces
88 do iface <- Map.lookup name interfaces
75− mainType <- Map.lookup "main" (Module.iTypes iface)
89+ mainType <- Map.lookup "main" (I._types iface)
77− message <-
90+ message <- getMessage mainType
78− case T.deepDealias mainType of
79− T.Type _program [_flags, _model, msg] -> Just msg
80− T.Type _node [msg] -> Just msg
83− let (msgType, msgDeps) = Writer.runWriter (extractHelp message)
92+ let (msgDeps, msgType) = run (extract message)
84− let (aliases, unions) = extractTransitive interfaces mempty msgDeps
93+ let (aliases, unions) = extractTransitive interfaces noDeps msgDeps
85− Just (Program msgType aliases unions)
94+ Just (T.Program msgType aliases unions)
88−type Alias =
97+getMessage :: Can.Annotation -> Maybe Can.Type
89− ( Text, [Text], Type )
98+getMessage (Can.Forall _ mainType) =
99+ case Type.deepDealias mainType of
100+ Can.TType _ _program [_flags, _model, msg] ->
103+ Can.TType _ _node [msg] ->
93− ( Text, [Text], [(Text, [Type])] )
107+ Nothing
96−extractTransitive :: Module.Interfaces -> Deps -> Deps -> ( [Alias], [Union] )
110+extractTransitive :: I.Interfaces -> Deps -> Deps -> ( [T.Alias], [T.Union] )
97−extractTransitive interfaces oldDeps currentDeps =
111+extractTransitive interfaces (Deps seenAliases seenUnions) (Deps nextAliases nextUnions) =
99− (aliases, unions) =
113+ aliases = Set.difference nextAliases seenAliases
100− diff oldDeps currentDeps
114+ unions = Set.difference nextUnions seenUnions
102 if Set.null aliases && Set.null unions then
116 if Set.null aliases && Set.null unions then
103 ( [], [] )
117 ( [], [] )
107− (result, newDeps) =
121+ (newDeps, result) =
108− Writer.runWriter $ do
122+ run $
109− publicAliases <- mapM (extractAlias interfaces) (Set.toList aliases)
124+ <$> traverse (extractAlias interfaces) (Set.toList aliases)
110− publicUnions <- mapM (extractUnion interfaces) (Set.toList unions)
125+ <*> traverse (extractUnion interfaces) (Set.toList unions)
111− return ( Maybe.catMaybes publicAliases, Maybe.catMaybes publicUnions )
126+
128+ Deps (Set.union seenAliases nextAliases) (Set.union seenUnions nextUnions)
113 remainingResult =
130 remainingResult =
114− extractTransitive interfaces (mappend oldDeps currentDeps) newDeps
131+ extractTransitive interfaces oldDeps newDeps
116 mappend result remainingResult
133 mappend result remainingResult
119−extractAlias :: Module.Interfaces -> Var.Canonical -> Writer.Writer Deps (Maybe Alias)
136+extractAlias :: I.Interfaces -> Opt.Global -> Extractor T.Alias
120−extractAlias interfaces var =
137+extractAlias interfaces (Opt.Global home name) =
122− toAlias (args, tipe) =
139+ (I.Interface _ _ aliases _) = interfaces ! home
123− (,,) (Var.toText var) args <$> extractHelp tipe
140+ (Can.Alias args aliasType _) = aliases ! name
125− traverse toAlias (get Module.iAliases interfaces var)
142+ T.Alias (toPublicName home name) args <$> extract aliasType
128−extractUnion :: Module.Interfaces -> Var.Canonical -> Writer.Writer Deps (Maybe Union)
145+extractUnion :: I.Interfaces -> Opt.Global -> Extractor T.Union
129−extractUnion interfaces var =
146+extractUnion interfaces (Opt.Global home name) =
131− toUnion (args, constructors) =
148+ (I.Interface _ unions _ _) = interfaces ! home
132− (,,) (Var.toText var) args
149+ (Can.Union args constructors) = unions ! name
133− <$> traverse (traverse (traverse extractHelp)) constructors
135− traverse toUnion (get Module.iUnions interfaces var)
151+ T.Union (toPublicName home name) args
152+ <$> traverse (traverse (traverse extract)) constructors
138−get :: (Module.Interface -> Map.Map Text a) -> Module.Interfaces -> Var.Canonical -> Maybe a
139−get getInfo interfaces var =
140− do (home, name) <- getHome var
141− iface <- Map.lookup home interfaces
142− Map.lookup name (getInfo iface)
161+ { _aliases :: Set.Set Opt.Global
162+ , _unions :: Set.Set Opt.Global
145−getHome :: Var.Canonical -> Maybe (ModuleName.Canonical, Text)
146−getHome (Var.Canonical home name) =
151− Var.Module moduleName ->
166+{-# NOINLINE noDeps #-}
152− Just (moduleName, name)
167+noDeps :: Deps
169+ Deps Set.empty Set.empty
154− Var.TopLevel moduleName ->
155− Just (moduleName, name)
158− Nothing
173+-- EXTRACTOR
176+newtype Extractor a =
180+ -> Set.Set Opt.Global
181+ -> (Set.Set Opt.Global -> Set.Set Opt.Global -> a -> result)
186+run :: Extractor a -> (Deps, a)
188+ k Set.empty Set.empty $ \aliases unions value ->
189+ ( Deps aliases unions, value )
192+addAlias :: Opt.Global -> a -> Extractor a
193+addAlias alias value =
194+ Extractor $ \aliases unions ok ->
195+ ok (Set.insert alias aliases) unions value
198+addUnion :: Opt.Global -> a -> Extractor a
199+addUnion union value =
200+ Extractor $ \aliases unions ok ->
201+ ok aliases (Set.insert union unions) value
204+instance Functor Extractor where
205+ fmap func (Extractor k) =
206+ Extractor $ \aliases unions ok ->
209+ ok a1 u1 (func value)
211+ k aliases unions ok1
214+instance Applicative Extractor where
216+ Extractor $ \aliases unions ok ->
217+ ok aliases unions value
219+ (<*>) (Extractor kf) (Extractor kv) =
220+ Extractor $ \aliases unions ok ->
225+ ok a2 u2 (func value)
229+ kf aliases unions ok1
232+instance Monad Extractor where
235+ (>>=) (Extractor ka) callback =
236+ Extractor $ \aliases unions ok ->
239+ case callback value of
240+ Extractor kb -> kb a1 u1 ok
242+ ka aliases unions ok1