never executed always true always false
    1 module AST.MatchReferences (MatchedNamespace(..), fromMatched, matchReferences, applyReferences) where
    2 
    3 import AST.V0_16
    4 import AST.Structure
    5 import Control.Applicative ((<|>))
    6 import Data.Coapplicative
    7 import ElmFormat.ImportInfo (ImportInfo)
    8 
    9 import qualified Data.Bimap as Bimap
   10 import qualified Data.Map.Strict as Dict
   11 import qualified Data.Maybe as Maybe
   12 import qualified Data.Set as Set
   13 import qualified ElmFormat.ImportInfo as ImportInfo
   14 
   15 
   16 data MatchedNamespace t
   17     = Local
   18     | MatchedImport Bool t -- Bool is True if it was originally qualified
   19     | Unmatched t -- The given namespace is clearly specified, but it is not a known import
   20     | UnmatchedUnqualified [t] -- An unqualified reference that doesn't match anything known. List is namespaces that we don't know the contents of that are possibilities for a match
   21     deriving (Eq, Ord, Show, Functor)
   22 
   23 
   24 fromMatched :: t -> MatchedNamespace t -> t
   25 fromMatched empty Local = empty
   26 fromMatched _ (MatchedImport _ t) = t
   27 fromMatched _ (Unmatched t) = t
   28 fromMatched empty (UnmatchedUnqualified _) = empty
   29 
   30 
   31 matchReferences ::
   32     (Coapplicative annf, Ord u) =>
   33     ImportInfo [u]
   34     -> ASTNS annf [u] kind
   35     -> ASTNS annf (MatchedNamespace [u]) kind
   36 matchReferences importInfo =
   37     let
   38         aliases = Bimap.toMap $ ImportInfo._aliases importInfo
   39         imports = ImportInfo._directImports importInfo
   40         exposed = ImportInfo._exposed importInfo
   41         unresolvedExposingAll = ImportInfo._unresolvedExposingAll importInfo
   42         unmatchedUnqualified = UnmatchedUnqualified $ Set.toList unresolvedExposingAll
   43 
   44         f locals ns identifier =
   45             case ns of
   46                 [] ->
   47                     case Dict.lookup identifier locals of
   48                         Just () -> Local
   49                         Nothing ->
   50                             case Dict.lookup identifier exposed of
   51                                 Nothing -> unmatchedUnqualified
   52                                 Just exposedFrom -> MatchedImport False exposedFrom
   53 
   54                 _ ->
   55                     let
   56                         self =
   57                             if Set.member ns imports then
   58                                 Just ns
   59                             else
   60                                 Nothing
   61 
   62                         fromAlias =
   63                             Dict.lookup ns aliases
   64 
   65                         resolved =
   66                             fromAlias <|> self
   67                     in
   68                     case resolved of
   69                         Nothing -> Unmatched ns
   70                         Just single -> MatchedImport True single
   71 
   72         defineLocal name = Dict.insert name ()
   73 
   74         mapTypeRef locals (ns, u) = (f locals ns (TypeName u), u)
   75         mapCtorRef locals (ns, u) = (f locals ns (CtorName u), u)
   76         mapVarRef locals (VarRef ns l) = VarRef (f locals ns (VarName l)) l
   77         mapVarRef locals (TagRef ns u) = TagRef (f locals ns (CtorName u)) u
   78         mapVarRef _ (OpRef op) = OpRef op
   79     in
   80     topDownReferencesWithContext
   81         defineLocal
   82         mapTypeRef mapCtorRef mapVarRef
   83         mempty
   84 
   85 
   86 applyReferences ::
   87     (Coapplicative annf, Ord u) =>
   88     ImportInfo [u]
   89     -> ASTNS annf (MatchedNamespace [u]) kind
   90     -> ASTNS annf [u] kind
   91 applyReferences importInfo =
   92     let
   93         aliases = Bimap.toMapR $ ImportInfo._aliases importInfo
   94         exposed = ImportInfo._exposed importInfo
   95         unresolvedExposingAll = ImportInfo._unresolvedExposingAll importInfo
   96 
   97         f locals ns' identifier =
   98             case ns' of
   99                 Local -> []
  100                 MatchedImport wasQualified ns ->
  101                     let
  102                         qualify =
  103                             case wasQualified of
  104                                 True ->
  105                                     (Dict.lookup identifier exposed /= Just ns) -- it's not exposed
  106                                     || Dict.member identifier locals -- something is locally defined with the same name
  107                                     || not (Set.null unresolvedExposingAll) -- there's an import with exposing(..) and we can't be sure if something exposed by that would conflict
  108                                 False ->
  109                                     (Dict.lookup identifier exposed /= Just ns) -- it's not exposed
  110                                     || Dict.member identifier locals -- something is locally defined with the same name
  111                     in
  112                     if qualify
  113                       then Maybe.fromMaybe ns $ Dict.lookup ns aliases
  114                       else [] -- This is exposed unambiguously and doesn't need to be qualified
  115                 Unmatched name -> name
  116                 UnmatchedUnqualified _ -> []
  117 
  118         defineLocal name = Dict.insert name ()
  119 
  120         mapTypeRef locals (ns, u) = (f locals ns (TypeName u), u)
  121         mapCtorRef locals (ns, u) = (f locals ns (CtorName u), u)
  122         mapVarRef locals (VarRef ns l) = VarRef (f locals ns (VarName l)) l
  123         mapVarRef locals (TagRef ns u) = TagRef (f locals ns (CtorName u)) u
  124         mapVarRef _ (OpRef op) = OpRef op
  125     in
  126     topDownReferencesWithContext
  127         defineLocal
  128         mapTypeRef mapCtorRef mapVarRef
  129         mempty