1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
5import Control.Monad (when)
6import Control.Monad.State.Strict (StateT, liftIO)
7import qualified Control.Monad.State.Strict as State
8import qualified Data.Char as Char
9import qualified Data.Map as Map
10import Data.Monoid ((<>))
11import qualified Data.Text as Text
12import Data.Text (Text)
14import qualified AST.Type as T
15import qualified AST.Variable as Var
16import qualified Reporting.Annotation as A
17import qualified Reporting.Error.Type as Error
18import qualified Reporting.Region as R
19import qualified Type.UnionFind as UF
31 = App1 Var.Canonical [Variable]
32 | Fun1 Variable Variable
34 | Record1 (Map.Map Text Variable) Variable
39 | AliasN Var.Canonical [(Text, Type)] Type
41 | AppN Var.Canonical [Type]
44 | RecordN (Map.Map Text Type) Type
56 , _copy :: Maybe Variable
62 | Var Flex (Maybe Super) (Maybe Text)
63 | Alias Var.Canonical [(Text,Variable)] Variable
101getVarNamesMark :: Int
113 | CEqual Error.Hint R.Region Type Type
115 | CLet [Scheme] Constraint
116 | CInstance R.Region SchemeName Type
119type SchemeName = Text
124 { _rigidQuantifiers :: [Variable]
125 , _flexibleQuantifiers :: [Variable]
126 , _constraint :: Constraint
127 , _header :: Map.Map Text (A.Located Type)
139(==>) :: Type -> Type -> Type
148mkDescriptor :: Content -> Descriptor
149mkDescriptor content =
158mkVar :: Maybe Super -> IO Variable
160 UF.fresh $ mkDescriptor (Var Flex maybeSuper Nothing)
163mkNamedVar :: Flex -> Text -> IO Variable
164mkNamedVar flex name =
165 UF.fresh $ mkDescriptor $ Var flex (toSuper name) (Just name)
168toSuper :: Text -> Maybe Super
170 if Text.isPrefixOf "number" name then
173 else if Text.isPrefixOf "comparable" name then
176 else if Text.isPrefixOf "appendable" name then
187monoscheme :: Map.Map Text (A.Located Type) -> Scheme
189 Scheme [] [] CTrue headers
195(/\) :: Constraint -> Constraint -> Constraint
203-- ex qs constraint == exists qs. constraint
204ex :: [Variable] -> Constraint -> Constraint
206 CLet [Scheme [] fqs constraint Map.empty] CTrue
209forall :: [Variable] -> Constraint -> Constraint
210forall rqs constraint =
211 CLet [Scheme rqs [] constraint Map.empty] CTrue
214exists :: (Type -> IO Constraint) -> IO Constraint
216 do v <- mkVar Nothing
217 ex [v] <$> f (VarN v)
220existsNumber :: (Type -> IO Constraint) -> IO Constraint
222 do v <- mkVar (Just Number)
223 ex [v] <$> f (VarN v)
227-- CONVERT TO SOURCE TYPES
230-- TODO: Attach resulting type to the descriptor so that you
231-- never have to do extra work, particularly nice for aliased types
232toSrcType :: Variable -> IO T.Canonical
234 do takenNames <- State.execStateT (getVarNames variable) Map.empty
235 State.evalStateT (variableToSrcType variable) (makeNameState takenNames)
238variableToSrcType :: Variable -> StateT NameState IO T.Canonical
239variableToSrcType variable =
240 do descriptor <- liftIO $ UF.descriptor variable
241 let mark = _mark descriptor
242 if mark == occursMark
247 do liftIO $ UF.modifyDescriptor variable (\desc -> desc { _mark = occursMark })
248 srcType <- contentToSrcType variable (_content descriptor)
249 liftIO $ UF.modifyDescriptor variable (\desc -> desc { _mark = mark })
253contentToSrcType :: Variable -> Content -> StateT NameState IO T.Canonical
254contentToSrcType variable content =
259 Var _ _ (Just name) ->
262 Var flex maybeSuper Nothing ->
263 do freshName <- getFreshName maybeSuper
264 liftIO $ UF.modifyDescriptor variable $ \desc ->
265 desc { _content = Var flex maybeSuper (Just freshName) }
266 return (T.Var freshName)
268 Alias name args realVariable ->
269 do srcArgs <- traverse (traverse variableToSrcType) args
270 srcType <- variableToSrcType realVariable
271 return (T.Aliased name srcArgs (T.Filled srcType))
277termToSrcType :: FlatType -> StateT NameState IO T.Canonical
281 T.Type name <$> traverse variableToSrcType args
285 <$> variableToSrcType a
286 <*> variableToSrcType b
289 return $ T.Record [] Nothing
291 Record1 fields extension ->
292 do srcFields <- Map.toList <$> traverse variableToSrcType fields
293 srcExt <- T.iteratedDealias <$> variableToSrcType extension
296 T.Record subFields subExt ->
297 T.Record (subFields ++ srcFields) subExt
300 T.Record srcFields (Just srcExt)
303 error "Used toSrcType on a type that is not well-formed"
307-- MANAGE FRESH VARIABLE NAMES
312 { _taken :: TakenNames
315 , _comparables :: Int
316 , _appendables :: Int
317 , _compAppends :: Int
321type TakenNames = Map.Map Text Variable
324makeNameState :: TakenNames -> NameState
326 NameState taken 0 0 0 0 0
329getFreshName :: (Monad m) => Maybe Super -> StateT NameState m Text
330getFreshName maybeSuper =
333 do index <- State.gets _normals
334 taken <- State.gets _taken
335 let (uniqueName, newIndex) = getFreshNormal index taken
336 State.modify (\state -> state { _normals = newIndex })
340 getFreshSuper "number" _numbers (\index state -> state { _numbers = index })
343 getFreshSuper "comparable" _comparables (\index state -> state { _comparables = index })
346 getFreshSuper "appendable" _appendables (\index state -> state { _appendables = index })
349 getFreshSuper "compappend" _compAppends (\index state -> state { _compAppends = index })
352getFreshNormal :: Int -> TakenNames -> (Text, Int)
353getFreshNormal index taken =
359 Char.chr (97 + letter)
362 Text.pack (if postfix <= 0 then [char] else char : show postfix)
364 if Map.member name taken then
365 getFreshNormal (index + 1) taken
374 -> (NameState -> Int)
375 -> (Int -> NameState -> NameState)
376 -> StateT NameState m Text
377getFreshSuper name getter setter =
378 do index <- State.gets getter
379 taken <- State.gets _taken
380 let (uniqueName, newIndex) = getFreshSuperHelp name index taken
381 State.modify (setter newIndex)
385getFreshSuperHelp :: Text -> Int -> TakenNames -> (Text, Int)
386getFreshSuperHelp name index taken =
389 if index <= 0 then name else name <> Text.pack (show index)
391 if Map.member newName taken then
392 getFreshSuperHelp name (index + 1) taken
399-- GET ALL VARIABLE NAMES
402getVarNames :: Variable -> StateT TakenNames IO ()
404 do desc <- liftIO $ UF.descriptor var
405 case _mark desc == getVarNamesMark of
410 do liftIO $ UF.setDescriptor var (desc { _mark = getVarNamesMark })
411 case _content desc of
418 Var flex maybeSuper (Just name) ->
419 do oldTaken <- State.get
420 newTaken <- liftIO $ addVarName 0 name var flex maybeSuper oldTaken
423 Alias _ args realVar ->
424 do mapM_ (getVarNames . snd) args
427 Structure (App1 _ args) ->
428 mapM_ getVarNames args
430 Structure (Fun1 arg body) ->
434 Structure EmptyRecord1 ->
437 Structure (Record1 fields extension) ->
438 do mapM_ getVarNames fields
439 getVarNames extension
442addVarName :: Int -> Text -> Variable -> Flex -> Maybe Super -> TakenNames -> IO TakenNames
443addVarName index givenName var flex maybeSuper taken =
446 makeIndexedName givenName index
448 case Map.lookup name taken of
450 do when (name /= givenName) $ UF.modifyDescriptor var $ \desc ->
451 desc { _content = Var flex maybeSuper (Just name) }
452 return $ Map.insert name var taken
455 do same <- UF.equivalent var otherVar
458 else addVarName (index + 1) givenName var flex maybeSuper taken
461makeIndexedName :: Text -> Int -> Text
462makeIndexedName name index =
466 else if Char.isDigit (Text.last name) then
467 name <> Text.pack ('_' : show index)
470 name <> Text.pack (show index)
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