@@ -1,45 +1,166 @@
1+{-# OPTIONS_GHC -Wall #-}
1−module Elm.Compiler.Type.Extract (toFullType, toAliasedType) where
2+module Elm.Compiler.Type.Extract
3−import Control.Arrow (second)
8+import qualified Control.Monad.Writer as Writer
9+import qualified Data.Map as Map
10+import qualified Data.Set as Set
11+import qualified AST.Module as Module
4−import qualified AST.Type as Type
12+import qualified AST.Module.Name as ModuleName
13+import qualified AST.Type as T
5import qualified AST.Variable as Var
14import qualified AST.Variable as Var
6−import qualified Elm.Compiler.Type as T
15+import Elm.Compiler.Type (Type(..), Program(Program))
9−toFullType :: Type.Canonical -> T.Type
14−toAliasedType :: Type.Canonical -> T.Type
15−toAliasedType astType =
22+extract :: T.Canonical -> Type
24+ fst $ Writer.runWriter $ extractHelp astType
19−toType :: Bool -> Type.Canonical -> T.Type
26+
20−toType useAliases astType =
27+type Deps =
28+ ( Set.Set Var.Canonical -- aliases
29+ , Set.Set Var.Canonical -- unions
33+diff :: Deps -> Deps -> Deps
34+diff (oldAliases, oldUnions) (newAliases, newUnions) =
35+ ( Set.difference newAliases oldAliases
36+ , Set.difference newUnions oldUnions
40+extractHelp :: T.Canonical -> Writer.Writer Deps Type
43+ T.Lambda arg result ->
44+ Lambda <$> extractHelp arg <*> extractHelp result
50+ do Writer.tell ( Set.empty, Set.singleton var )
51+ return $ Type $ Var.toString var
53+ T.App constructor args ->
54+ App <$> extractHelp constructor <*> traverse extractHelp args
56+ T.Record fields ext ->
58+ <$> traverse (traverse extractHelp) fields
59+ <*> traverse extractHelp ext
61+ T.Aliased name args aliasedType ->
62+ do Writer.tell ( Set.singleton name, Set.empty )
63+ _ <- extractHelp (T.dealias args aliasedType)
64+ App (Type (Var.toString name)) <$> traverse (extractHelp . snd) args
68+-- EXTRACT MODEL, MSG, AND ANY TRANSITIVE DEPENDENCIES
71+extractProgram :: Module.Interfaces -> ModuleName.Canonical -> Maybe Program
72+extractProgram interfaces name =
73+ do iface <- Map.lookup name interfaces
74+ mainType <- Map.lookup "main" (Module.iTypes iface)
76+ T.App _program [_flags, model, msg] ->
78+ (modelType, modelDeps) =
79+ Writer.runWriter (extractHelp model)
82+ Writer.runWriter (extractHelp msg)
85+ extractTransitive interfaces mempty (mappend modelDeps msgDeps)
87+ Just $ Program modelType msgType aliases unions
94+ ( String, [String], Type )
98+ ( String, [String], [(String, [Type])] )
101+extractTransitive :: Module.Interfaces -> Deps -> Deps -> ( [Alias], [Union] )
102+extractTransitive interfaces oldDeps currentDeps =
22− go = toType useAliases
104+ (aliases, unions) =
105+ diff oldDeps currentDeps
24− case astType of
107+ if Set.null aliases && Set.null unions then
25− Type.Lambda t1 t2 ->
108+ ( [], [] )
26− T.Lambda (go t1) (go t2)
109+
115+ <$> mapM (extractAlias interfaces) (Set.toList aliases)
116+ <*> mapM (extractUnion interfaces) (Set.toList unions)
119+ extractTransitive interfaces (mappend oldDeps currentDeps) newDeps
121+ mappend result remainingResult
124+extractAlias :: Module.Interfaces -> Var.Canonical -> Writer.Writer Deps Alias
125+extractAlias interfaces var =
126+ case get Module.iAliases interfaces var of
128+ return ( Var.toString var, [], Type "_Tuple0" )
130+ Just (args, tipe) ->
131+ (,,) (Var.toString var) args
132+ <$> extractHelp tipe
135+extractUnion :: Module.Interfaces -> Var.Canonical -> Writer.Writer Deps Union
136+extractUnion interfaces var =
137+ case get Module.iUnions interfaces var of
139+ return ( Var.toString var, [], [] )
141+ Just (args, constructors) ->
142+ (,,) (Var.toString var) args
143+ <$> traverse (traverse (traverse extractHelp)) constructors
28− Type.Var x ->
146+get :: (Module.Interface -> Map.Map String a) -> Module.Interfaces -> Var.Canonical -> Maybe a
29− T.Var x
147+get getInfo interfaces var =
148+ do (home, name) <- getHome var
149+ iface <- Map.lookup home interfaces
150+ Map.lookup name (getInfo iface)
32− T.Type (Var.toString var)
34− Type.App t ts ->
153+getHome :: Var.Canonical -> Maybe (ModuleName.Canonical, String)
35− T.App (go t) (map go ts)
154+getHome (Var.Canonical home name) =
37− Type.Record fields ext ->
159+ Var.Module moduleName ->
38− T.Record (map (second go) fields) (fmap go ext)
160+ Just (moduleName, name)
40− Type.Aliased name args t ->
162+ Var.TopLevel moduleName ->
41− if useAliases then
163+ Just (moduleName, name)
42− T.App (T.Type (Var.toString name)) (map (go . snd) args)
44− else
165+ Var.Local ->
45− go (Type.dealias args t)
166+ Nothing