1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
9 , Descriptor(Descriptor)
18 , int, float, char, string, bool, never
19 , vec2, vec3, vec4, mat4, texture
32import Control.Monad.State.Strict (StateT, liftIO)
33import qualified Control.Monad.State.Strict as State
34import Data.Foldable (foldrM)
35import qualified Data.Map.Strict as Map
36import qualified Data.Name as Name
37import Data.Word (Word32)
39import qualified AST.Canonical as Can
40import qualified AST.Utils.Type as Type
41import qualified Elm.ModuleName as ModuleName
42import qualified Reporting.Annotation as A
43import qualified Reporting.Error.Type as E
44import qualified Type.Error as ET
45import qualified Type.UnionFind as UF
55 | CEqual A.Region E.Category Type (E.Expected Type)
56 | CLocal A.Region Name.Name (E.Expected Type)
57 | CForeign A.Region Name.Name Can.Annotation (E.Expected Type)
58 | CPattern A.Region E.PCategory Type (E.PExpected Type)
61 { _rigidVars :: [Variable]
62 , _flexVars :: [Variable]
63 , _header :: Map.Map Name.Name (A.Located Type)
64 , _headerCon :: Constraint
65 , _bodyCon :: Constraint
69exists :: [Variable] -> Constraint -> Constraint
70exists flexVars constraint =
71 CLet [] flexVars Map.empty constraint CTrue
83 = App1 ModuleName.Canonical Name.Name [Variable]
84 | Fun1 Variable Variable
86 | Record1 (Map.Map Name.Name Variable) Variable
88 | Tuple1 Variable Variable (Maybe Variable)
92 = PlaceHolder Name.Name
93 | AliasN ModuleName.Canonical Name.Name [(Name.Name, Type)] Type
95 | AppN ModuleName.Canonical Name.Name [Type]
98 | RecordN (Map.Map Name.Name Type) Type
100 | TupleN Type Type (Maybe Type)
109 { _content :: Content
112 , _copy :: Maybe Variable
117 = FlexVar (Maybe Name.Name)
118 | FlexSuper SuperType (Maybe Name.Name)
120 | RigidSuper SuperType Name.Name
122 | Alias ModuleName.Canonical Name.Name [(Name.Name,Variable)] Variable
134makeDescriptor :: Content -> Descriptor
135makeDescriptor content =
136 Descriptor content noRank noMark Nothing
157newtype Mark = Mark Word32
171getVarNamesMark :: Mark
176{-# INLINE nextMark #-}
177nextMark :: Mark -> Mark
178nextMark (Mark mark) =
190(==>) :: Type -> Type -> Type
201int = AppN ModuleName.basics "Int" []
204{-# NOINLINE float #-}
206float = AppN ModuleName.basics "Float" []
211char = AppN ModuleName.char "Char" []
214{-# NOINLINE string #-}
216string = AppN ModuleName.string "String" []
221bool = AppN ModuleName.basics "Bool" []
224{-# NOINLINE never #-}
226never = AppN ModuleName.basics "Never" []
235vec2 = AppN ModuleName.vector2 "Vec2" []
240vec3 = AppN ModuleName.vector3 "Vec3" []
245vec4 = AppN ModuleName.vector4 "Vec4" []
250mat4 = AppN ModuleName.matrix4 "Mat4" []
253{-# NOINLINE texture #-}
255texture = AppN ModuleName.texture "Texture" []
259-- MAKE FLEX VARIABLES
262mkFlexVar :: IO Variable
264 UF.fresh flexVarDescriptor
267{-# NOINLINE flexVarDescriptor #-}
268flexVarDescriptor :: Descriptor
270 makeDescriptor unnamedFlexVar
273{-# NOINLINE unnamedFlexVar #-}
274unnamedFlexVar :: Content
283mkFlexNumber :: IO Variable
285 UF.fresh flexNumberDescriptor
288{-# NOINLINE flexNumberDescriptor #-}
289flexNumberDescriptor :: Descriptor
290flexNumberDescriptor =
291 makeDescriptor (unnamedFlexSuper Number)
294unnamedFlexSuper :: SuperType -> Content
295unnamedFlexSuper super =
296 FlexSuper super Nothing
300-- MAKE NAMED VARIABLES
303nameToFlex :: Name.Name -> IO Variable
305 UF.fresh $ makeDescriptor $
306 maybe FlexVar FlexSuper (toSuper name) (Just name)
309nameToRigid :: Name.Name -> IO Variable
311 UF.fresh $ makeDescriptor $
312 maybe RigidVar RigidSuper (toSuper name) name
315toSuper :: Name.Name -> Maybe SuperType
317 if Name.isNumberType name then
320 else if Name.isComparableType name then
323 else if Name.isAppendableType name then
326 else if Name.isCompappendType name then
337toAnnotation :: Variable -> IO Can.Annotation
338toAnnotation variable =
339 do userNames <- getVarNames variable Map.empty
340 (tipe, NameState freeVars _ _ _ _ _) <-
341 State.runStateT (variableToCanType variable) (makeNameState userNames)
342 return $ Can.Forall freeVars tipe
345variableToCanType :: Variable -> StateT NameState IO Can.Type
346variableToCanType variable =
347 do (Descriptor content _ _ _) <- liftIO $ UF.get variable
355 return (Can.TVar name)
358 do name <- getFreshVarName
359 liftIO $ UF.modify variable (\desc -> desc { _content = FlexVar (Just name) })
360 return (Can.TVar name)
362 FlexSuper super maybeName ->
365 return (Can.TVar name)
368 do name <- getFreshSuperName super
369 liftIO $ UF.modify variable (\desc -> desc { _content = FlexSuper super (Just name) })
370 return (Can.TVar name)
373 return (Can.TVar name)
376 return (Can.TVar name)
378 Alias home name args realVariable ->
379 do canArgs <- traverse (traverse variableToCanType) args
380 canType <- variableToCanType realVariable
381 return (Can.TAlias home name canArgs (Can.Filled canType))
384 error "cannot handle Error types in variableToCanType"
387termToCanType :: FlatType -> StateT NameState IO Can.Type
390 App1 home name args ->
391 Can.TType home name <$> traverse variableToCanType args
395 <$> variableToCanType a
396 <*> variableToCanType b
399 return $ Can.TRecord Map.empty Nothing
401 Record1 fields extension ->
402 do canFields <- traverse fieldToCanType fields
403 canExt <- Type.iteratedDealias <$> variableToCanType extension
406 Can.TRecord subFields subExt ->
407 Can.TRecord (Map.union subFields canFields) subExt
410 Can.TRecord canFields (Just name)
413 error "Used toAnnotation on a type that is not well-formed"
420 <$> variableToCanType a
421 <*> variableToCanType b
422 <*> traverse variableToCanType maybeC
425fieldToCanType :: Variable -> StateT NameState IO Can.FieldType
426fieldToCanType variable =
427 do tipe <- variableToCanType variable
428 return (Can.FieldType 0 tipe)
435toErrorType :: Variable -> IO ET.Type
436toErrorType variable =
437 do userNames <- getVarNames variable Map.empty
438 State.evalStateT (variableToErrorType variable) (makeNameState userNames)
441variableToErrorType :: Variable -> StateT NameState IO ET.Type
442variableToErrorType variable =
443 do descriptor <- liftIO $ UF.get variable
444 let mark = _mark descriptor
445 if mark == occursMark
450 do liftIO $ UF.modify variable (\desc -> desc { _mark = occursMark })
451 errType <- contentToErrorType variable (_content descriptor)
452 liftIO $ UF.modify variable (\desc -> desc { _mark = mark })
456contentToErrorType :: Variable -> Content -> StateT NameState IO ET.Type
457contentToErrorType variable content =
465 return (ET.FlexVar name)
468 do name <- getFreshVarName
469 liftIO $ UF.modify variable (\desc -> desc { _content = FlexVar (Just name) })
470 return (ET.FlexVar name)
472 FlexSuper super maybeName ->
475 return (ET.FlexSuper (superToSuper super) name)
478 do name <- getFreshSuperName super
479 liftIO $ UF.modify variable (\desc -> desc { _content = FlexSuper super (Just name) })
480 return (ET.FlexSuper (superToSuper super) name)
483 return (ET.RigidVar name)
485 RigidSuper super name ->
486 return (ET.RigidSuper (superToSuper super) name)
488 Alias home name args realVariable ->
489 do errArgs <- traverse (traverse variableToErrorType) args
490 errType <- variableToErrorType realVariable
491 return (ET.Alias home name errArgs errType)
497superToSuper :: SuperType -> ET.Super
501 Comparable -> ET.Comparable
502 Appendable -> ET.Appendable
503 CompAppend -> ET.CompAppend
506termToErrorType :: FlatType -> StateT NameState IO ET.Type
507termToErrorType term =
509 App1 home name args ->
510 ET.Type home name <$> traverse variableToErrorType args
513 do arg <- variableToErrorType a
514 result <- variableToErrorType b
517 ET.Lambda arg1 arg2 others ->
518 ET.Lambda arg arg1 (arg2:others)
521 ET.Lambda arg result []
524 return $ ET.Record Map.empty ET.Closed
526 Record1 fields extension ->
527 do errFields <- traverse variableToErrorType fields
528 errExt <- ET.iteratedDealias <$> variableToErrorType extension
531 ET.Record subFields subExt ->
532 ET.Record (Map.union subFields errFields) subExt
535 ET.Record errFields (ET.FlexOpen ext)
538 ET.Record errFields (ET.RigidOpen ext)
541 error "Used toErrorType on a type that is not well-formed"
548 <$> variableToErrorType a
549 <*> variableToErrorType b
550 <*> traverse variableToErrorType maybeC
554-- MANAGE FRESH VARIABLE NAMES
559 { _taken :: Map.Map Name.Name ()
562 , _comparables :: Int
563 , _appendables :: Int
564 , _compAppends :: Int
568makeNameState :: Map.Map Name.Name Variable -> NameState
570 NameState (Map.map (const ()) taken) 0 0 0 0 0
577getFreshVarName :: (Monad m) => StateT NameState m Name.Name
579 do index <- State.gets _normals
580 taken <- State.gets _taken
581 let (name, newIndex, newTaken) = getFreshVarNameHelp index taken
582 State.modify $ \state -> state { _taken = newTaken, _normals = newIndex }
586getFreshVarNameHelp :: Int -> Map.Map Name.Name () -> (Name.Name, Int, Map.Map Name.Name ())
587getFreshVarNameHelp index taken =
590 Name.fromTypeVariableScheme index
592 if Map.member name taken then
593 getFreshVarNameHelp (index + 1) taken
595 ( name, index + 1, Map.insert name () taken )
602getFreshSuperName :: (Monad m) => SuperType -> StateT NameState m Name.Name
603getFreshSuperName super =
606 getFreshSuper "number" _numbers (\index state -> state { _numbers = index })
609 getFreshSuper "comparable" _comparables (\index state -> state { _comparables = index })
612 getFreshSuper "appendable" _appendables (\index state -> state { _appendables = index })
615 getFreshSuper "compappend" _compAppends (\index state -> state { _compAppends = index })
618getFreshSuper :: (Monad m) => Name.Name -> (NameState -> Int) -> (Int -> NameState -> NameState) -> StateT NameState m Name.Name
619getFreshSuper prefix getter setter =
620 do index <- State.gets getter
621 taken <- State.gets _taken
622 let (name, newIndex, newTaken) = getFreshSuperHelp prefix index taken
623 State.modify (\state -> setter newIndex state { _taken = newTaken })
627getFreshSuperHelp :: Name.Name -> Int -> Map.Map Name.Name () -> (Name.Name, Int, Map.Map Name.Name ())
628getFreshSuperHelp prefix index taken =
631 Name.fromTypeVariable prefix index
633 if Map.member name taken then
634 getFreshSuperHelp prefix (index + 1) taken
637 ( name, index + 1, Map.insert name () taken )
641-- GET ALL VARIABLE NAMES
644getVarNames :: Variable -> Map.Map Name.Name Variable -> IO (Map.Map Name.Name Variable)
645getVarNames var takenNames =
646 do (Descriptor content rank mark copy) <- UF.get var
647 if mark == getVarNamesMark
648 then return takenNames
650 do UF.set var (Descriptor content rank getVarNamesMark copy)
661 addName 0 name var (FlexVar . Just) takenNames
663 FlexSuper super maybeName ->
669 addName 0 name var (FlexSuper super . Just) takenNames
672 addName 0 name var RigidVar takenNames
674 RigidSuper super name ->
675 addName 0 name var (RigidSuper super) takenNames
678 foldrM getVarNames takenNames (map snd args)
680 Structure flatType ->
683 foldrM getVarNames takenNames args
686 getVarNames arg =<< getVarNames body takenNames
691 Record1 fields extension ->
692 getVarNames extension =<<
693 foldrM getVarNames takenNames (Map.elems fields)
698 Tuple1 a b Nothing ->
699 getVarNames a =<< getVarNames b takenNames
701 Tuple1 a b (Just c) ->
702 getVarNames a =<< getVarNames b =<< getVarNames c takenNames
706-- REGISTER NAME / RENAME DUPLICATES
709addName :: Int -> Name.Name -> Variable -> (Name.Name -> Content) -> Map.Map Name.Name Variable -> IO (Map.Map Name.Name Variable)
710addName index givenName var makeContent takenNames =
713 Name.fromTypeVariable givenName index
715 case Map.lookup indexedName takenNames of
717 do if indexedName == givenName then return () else
718 UF.modify var $ \(Descriptor _ rank mark copy) ->
719 Descriptor (makeContent indexedName) rank mark copy
720 return $ Map.insert indexedName var takenNames
723 do same <- UF.equivalent var otherVar
725 then return takenNames
726 else addName (index + 1) givenName var makeContent takenNames
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