4import qualified Data.Map as Map
5import qualified Data.List as List
6import qualified Type.Environment as Env
7import qualified Data.UnionFind.IO as UF
8import Control.Monad.State
9import Control.Applicative ((<$>),(<*>), Applicative)
10import qualified Data.Traversable as Traversable
11import Text.PrettyPrint as P
12import SourceSyntax.PrettyPrint
13import SourceSyntax.Location
14import qualified SourceSyntax.Type as Src
15import qualified Type.Alias as Alias
18-- Holds a bunch of variables
19-- The rank of each variable is less than or equal to the pool's "maxRank"
20-- The young pool exists to make it possible to identify these vars in constant time.
24 inhabitants :: [Variable]
27emptyPool = Pool { maxRank = outermostRank, inhabitants = [] }
29type Env = Map.Map String Variable
31-- Keeps track of the environment, type variable pool, and a list of errors
32data SolverState = SS {
37 sErrors :: [Alias.Rules -> IO P.Doc]
42 sSavedEnv = Map.empty,
44 sMark = noMark + 1, -- The mark must never be equal to noMark!
48modifyEnv f = modify $ \state -> state { sEnv = f (sEnv state) }
49modifyPool f = modify $ \state -> state { sPool = f (sPool state) }
51addError span hint t1 t2 =
52 modify $ \state -> state { sErrors = makeError : sErrors state }
55 let prettiest = pretty . Alias.realias rules
56 t1' <- prettiest <$> toSrcType t1
57 t2' <- prettiest <$> toSrcType t2
59 [ P.text $ "Type error" ++ location ++ ":"
60 , maybe P.empty P.text hint
61 , display $ case span of { NoSpan msg -> msg ; Span _ _ msg -> msg }
62 , P.text " Expected Type:" <+> t1'
63 , P.text " Actual Type:" <+> t2'
66 location = case span of
69 if line p1 == line p2 then " on line " ++ show (line p1)
70 else " between lines " ++ show (line p1) ++ " and " ++ show (line p2)
73 P.vcat [ P.text $ concatMap ("\n "++) (lines msg)
77switchToPool pool = modifyPool (\_ -> pool)
79getPool :: StateT SolverState IO Pool
80getPool = sPool <$> get
82getEnv :: StateT SolverState IO Env
85saveLocalEnv :: StateT SolverState IO ()
88 modify $ \state -> state { sSavedEnv = env }
90uniqueMark :: StateT SolverState IO Int
93 let mark = sMark state
94 put $ state { sMark = mark + 1 }
97nextRankPool :: StateT SolverState IO Pool
100 return $ Pool { maxRank = maxRank pool + 1, inhabitants = [] }
102register :: Variable -> StateT SolverState IO Variable
103register variable = do
104 modifyPool $ \pool -> pool { inhabitants = variable : inhabitants pool }
107introduce :: Variable -> StateT SolverState IO Variable
108introduce variable = do
110 liftIO $ UF.modifyDescriptor variable (\desc -> desc { rank = maxRank pool })
113flatten :: Type -> StateT SolverState IO Variable
118 flatStructure <- traverseTerm flatten t
120 var <- liftIO . UF.fresh $ Descriptor {
121 structure = Just flatStructure,
130makeInstance :: Variable -> StateT SolverState IO Variable
132 alreadyCopied <- uniqueMark
133 freshVar <- makeCopy alreadyCopied var
134 restore alreadyCopied var
137makeCopy :: Int -> Variable -> StateT SolverState IO Variable
138makeCopy alreadyCopied variable = do
139 desc <- liftIO $ UF.descriptor variable
141 () | mark desc == alreadyCopied ->
144 Nothing -> error $ "Error copying type variable. This should be impossible." ++
145 " Please report an error to the github repo!"
147 | rank desc /= noRank || flex desc == Constant ->
152 newVar <- liftIO $ UF.fresh $ Descriptor {
156 flex = case flex desc of
160 name = case flex desc of
166 -- Link the original variable to the new variable. This lets us
167 -- avoid making multiple copies of the variable we are instantiating.
169 -- Need to do this before recursively copying the structure of
170 -- the variable to avoid looping on cyclic terms.
171 liftIO $ UF.modifyDescriptor variable $ \desc ->
172 desc { mark = alreadyCopied, copy = Just newVar }
174 -- Now we recursively copy the structure of the variable.
175 -- We have already marked the variable as copied, so we
176 -- will not repeat this work or crawl this variable again.
177 case structure desc of
178 Nothing -> return newVar
180 newTerm <- traverseTerm (makeCopy alreadyCopied) term
181 liftIO $ UF.modifyDescriptor newVar $ \desc ->
182 desc { structure = Just newTerm }
185restore :: Int -> Variable -> StateT SolverState IO Variable
186restore alreadyCopied variable = do
187 desc <- liftIO $ UF.descriptor variable
188 if mark desc /= alreadyCopied
192 Traversable.traverse (traverseTerm (restore alreadyCopied)) (structure desc)
193 liftIO $ UF.modifyDescriptor variable $ \desc ->
194 desc { mark = noMark, rank = noRank, structure = restoredStructure }
197traverseTerm :: (Monad f, Applicative f) => (a -> f b) -> Term1 a -> f (Term1 b)
200 App1 a b -> App1 <$> f a <*> f b
201 Fun1 a b -> Fun1 <$> f a <*> f b
202 Var1 x -> Var1 <$> f x
203 EmptyRecord1 -> return EmptyRecord1
204 Record1 fields ext ->
205 Record1 <$> Traversable.traverse (mapM f) fields <*> f ext
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list