@@ -1,15 +1,20 @@
1{-# OPTIONS_GHC -Wall #-}
1{-# OPTIONS_GHC -Wall #-}
2−{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE BangPatterns, OverloadedStrings, Rank2Types #-}
3−{-# LANGUAGE Rank2Types #-}
4module Elm.Compiler.Type.Extract
3module Elm.Compiler.Type.Extract
5 ( fromAnnotation
4 ( fromAnnotation
10+ , fromDependencyInterface
12import Data.Map ((!))
16import Data.Map ((!))
17+import qualified Data.Map as Map
13import qualified Data.Maybe as Maybe
18import qualified Data.Maybe as Maybe
14import qualified Data.Name as Name
19import qualified Data.Name as Name
15import qualified Data.Set as Set
20import qualified Data.Set as Set
@@ -77,23 +82,70 @@ toPublicName (ModuleName.Canonical _ home) name =
85+-- TRANSITIVELY AVAILABLE TYPES
89+ Types (Map.Map ModuleName.Canonical Types_)
90+ -- TODO profile Opt.Global representation
91+ -- current representation needs less allocation
92+ -- but maybe the lookup is much worse
97+ { _union_info :: Map.Map Name.Name Can.Union
98+ , _alias_info :: Map.Map Name.Name Can.Alias
102+mergeMany :: [Types] -> Types
103+mergeMany listOfTypes =
105+ [] -> Types Map.empty
106+ t:ts -> foldr merge t ts
109+merge :: Types -> Types -> Types
110+merge (Types types1) (Types types2) =
111+ Types (Map.union types1 types2)
114+fromInterface :: ModuleName.Raw -> I.Interface -> Types
115+fromInterface name (I.Interface pkg _ unions aliases _) =
116+ Types $ Map.singleton (ModuleName.Canonical pkg name) $
117+ Types_ (Map.map I.extractUnion unions) (Map.map I.extractAlias aliases)
120+fromDependencyInterface :: ModuleName.Canonical -> I.DependencyInterface -> Types
121+fromDependencyInterface home di =
122+ Types $ Map.singleton home $
124+ I.Public (I.Interface _ _ unions aliases _) ->
125+ Types_ (Map.map I.extractUnion unions) (Map.map I.extractAlias aliases)
127+ I.Private _ unions aliases ->
128+ Types_ unions aliases
80-- EXTRACT MODEL, MSG, AND ANY TRANSITIVE DEPENDENCIES
132-- EXTRACT MODEL, MSG, AND ANY TRANSITIVE DEPENDENCIES
83−fromMsg :: I.Interfaces -> Can.Type -> T.DebugMetadata
135+fromMsg :: Types -> Can.Type -> T.DebugMetadata
84−fromMsg interfaces message =
136+fromMsg types message =
86 (msgDeps, msgType) =
138 (msgDeps, msgType) =
87 run (extract message)
139 run (extract message)
89 (aliases, unions) =
141 (aliases, unions) =
90− extractTransitive interfaces noDeps msgDeps
142+ extractTransitive types noDeps msgDeps
92 T.DebugMetadata msgType aliases unions
144 T.DebugMetadata msgType aliases unions
95−extractTransitive :: I.Interfaces -> Deps -> Deps -> ( [T.Alias], [T.Union] )
147+extractTransitive :: Types -> Deps -> Deps -> ( [T.Alias], [T.Union] )
96−extractTransitive interfaces (Deps seenAliases seenUnions) (Deps nextAliases nextUnions) =
148+extractTransitive types (Deps seenAliases seenUnions) (Deps nextAliases nextUnions) =
98 aliases = Set.difference nextAliases seenAliases
150 aliases = Set.difference nextAliases seenAliases
99 unions = Set.difference nextUnions seenUnions
151 unions = Set.difference nextUnions seenUnions
@@ -106,39 +158,36 @@ extractTransitive interfaces (Deps seenAliases seenUnions) (Deps nextAliases nex
106 (newDeps, result) =
158 (newDeps, result) =
109− <$> traverse (extractAlias interfaces) (Set.toList aliases)
161+ <$> traverse (extractAlias types) (Set.toList aliases)
110− <*> traverse (extractUnion interfaces) (Set.toList unions)
162+ <*> traverse (extractUnion types) (Set.toList unions)
112 oldDeps =
164 oldDeps =
113 Deps (Set.union seenAliases nextAliases) (Set.union seenUnions nextUnions)
165 Deps (Set.union seenAliases nextAliases) (Set.union seenUnions nextUnions)
115 remainingResult =
167 remainingResult =
116− extractTransitive interfaces oldDeps newDeps
168+ extractTransitive types oldDeps newDeps
118 mappend result remainingResult
170 mappend result remainingResult
121−extractAlias :: I.Interfaces -> Opt.Global -> Extractor T.Alias
173+extractAlias :: Types -> Opt.Global -> Extractor T.Alias
122−extractAlias interfaces (Opt.Global home name) =
174+extractAlias (Types dict) (Opt.Global home name) =
124− (I.Interface _ _ aliases _) = interfaces ! home
125− (Can.Alias args aliasType) = I.toAliasInternals (aliases ! name)
176+ (Can.Alias args aliasType) = _alias_info (dict ! home) ! name
127 T.Alias (toPublicName home name) args <$> extract aliasType
178 T.Alias (toPublicName home name) args <$> extract aliasType
130−extractUnion :: I.Interfaces -> Opt.Global -> Extractor T.Union
181+extractUnion :: Types -> Opt.Global -> Extractor T.Union
131−extractUnion interfaces (Opt.Global home name) =
182+extractUnion (Types dict) (Opt.Global home name) =
132 if name == Name.list && home == ModuleName.list
183 if name == Name.list && home == ModuleName.list
133 then return $ T.Union (toPublicName home name) ["a"] []
184 then return $ T.Union (toPublicName home name) ["a"] []
136 pname = toPublicName home name
187 pname = toPublicName home name
137− unions = I._unions (interfaces ! home)
188+ (Can.Union vars ctors _ _) = _union_info (dict ! home) ! name
139− case I.toUnionInternals (unions ! name) of
140− Can.Union vars ctors _ _ ->
141− T.Union pname vars <$> traverse extractCtor ctors
190+ T.Union pname vars <$> traverse extractCtor ctors
144extractCtor :: Can.Ctor -> Extractor (Name.Name, [T.Type])
193extractCtor :: Can.Ctor -> Extractor (Name.Name, [T.Type])