1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
3module Canonicalize.Variable (Result, variable, tvar, pvar) where
5import Data.Monoid ((<>))
6import qualified Data.Either as Either
7import qualified Data.Map as Map
8import qualified Data.Set as Set
9import qualified Data.Text as Text
10import Data.Text (Text)
12import qualified AST.Helpers as Help
13import qualified AST.Module.Name as ModuleName
14import qualified AST.Type as Type
15import qualified AST.Variable as Var
16import qualified Canonicalize.Environment as Env
17import qualified Reporting.Error.Canonicalize as Error
18import qualified Reporting.Helpers as Help (nearbyNames)
19import qualified Reporting.Region as R
20import qualified Reporting.Result as Result
21import qualified Reporting.Warning as Warning
22import Elm.Utils ((|>))
30 Result.Result (Set.Set ModuleName.Raw) Warning.Warning Error.Error a
33logVarWith :: (a -> Var.Canonical) -> a -> Result a
34logVarWith toVar value =
36 Var.Canonical (Var.Module (ModuleName.Canonical _ moduleName)) _name ->
37 Result.accumulate (Set.singleton moduleName) value
43logVar :: Var.Canonical -> Result Var.Canonical
52variable :: R.Region -> Env.Env -> Text -> Result Var.Canonical
53variable region env var =
55 Right (name, varName) | ModuleName.isKernel name ->
58 ModuleName._package (Env._home env)
61 ModuleName.Canonical localPkg name
63 logVar (Var.Canonical (Var.Module moduleName) varName)
66 case Set.toList <$> Map.lookup var (Env._values env) of
71 preferLocals region env "variable" vs var
74 notFound region "variable" (Map.keys (Env._values env)) var
77tvar :: R.Region -> Env.Env -> Text -> Result (Either Var.Canonical (Var.Canonical, [Text], Type.Canonical))
79 case unions ++ aliases of
80 [] -> notFound region "type" (Map.keys (Env._unions env) ++ Map.keys (Env._aliases env)) var
81 [v] -> logVarWith extract v
82 vs -> preferLocals' region env extract "type" vs var
85 map Left (maybe [] Set.toList (Map.lookup var (Env._unions env)))
88 map Right (maybe [] Set.toList (Map.lookup var (Env._aliases env)))
96pvar :: R.Region -> Env.Env -> Text -> Int -> Result Var.Canonical
97pvar region env var actualArgs =
98 case Set.toList <$> Map.lookup var (Env._patterns env) of
103 foundArgCheck =<< preferLocals' region env fst "pattern" values var
106 notFound region "pattern" (Map.keys (Env._patterns env)) var
108 foundArgCheck (name, expectedArgs) =
109 if actualArgs == expectedArgs then
113 Result.throw region (Error.argMismatch name expectedArgs actualArgs)
120preferLocals :: R.Region -> Env.Env -> Text -> [Var.Canonical] -> Text -> Result Var.Canonical
121preferLocals region env =
122 preferLocals' region env id
128 -> (a -> Var.Canonical)
133preferLocals' region env extract kind possibilities var =
134 case filter (isLocal (Env._home env) . extract) possibilities of
136 ambiguous possibilities
141 --Local vars shadow top-level vars
143 | isTopLevel (extract v1) ->
144 logVarWith extract v2
146 | isTopLevel (extract v2) ->
147 logVarWith extract v1
152 ambiguous possibleVars =
153 Result.throw region (Error.variable kind var Error.Ambiguous vars)
155 vars = map (Var.toText . extract) possibleVars
158isLocal :: ModuleName.Canonical -> Var.Canonical -> Bool
159isLocal contextName (Var.Canonical home _) =
174isTopLevel :: Var.Canonical -> Bool
175isTopLevel (Var.Canonical home _) =
189 Either Text (ModuleName.Raw, Text)
192toVarName :: Text -> VarName
194 case Text.splitOn "." var of
196 xs -> Right (Text.intercalate "." (init xs), last xs)
199noQualifier :: VarName -> Text
206qualifiedToText :: (ModuleName.Raw, Text) -> Text
207qualifiedToText (modul, name) =
208 ModuleName.toText modul <> "." <> name
211isOp :: VarName -> Bool
213 Help.isOp (noQualifier name)
220notFound :: R.Region -> Text -> [Text] -> Text -> Result a
221notFound region kind possibilities var =
226 map toVarName possibilities
228 (problem, suggestions) =
231 exposedProblem name possibleNames
233 Right (modul, varName) ->
234 qualifiedProblem modul varName (Either.rights possibleNames)
236 Result.throw region (Error.variable kind var problem suggestions)
239exposedProblem :: VarName -> [VarName] -> (Error.VarProblem, [Text])
240exposedProblem name possibleNames =
241 let (exposed, qualified) =
243 |> filter (\n -> isOp name == isOp n)
244 |> Help.nearbyNames noQualifier name
245 |> Either.partitionEithers
247 ( Error.ExposedUnknown
248 , exposed ++ map qualifiedToText qualified
252qualifiedProblem :: ModuleName.Raw -> Text -> [(ModuleName.Raw, Text)] -> (Error.VarProblem, [Text])
253qualifiedProblem moduleName name allQualified =
254 let availableModules =
255 Set.fromList (map fst allQualified)
257 case Set.member moduleName availableModules of
259 ( Error.QualifiedUnknown moduleName name
261 |> filter ((==) moduleName . fst)
263 |> Help.nearbyNames id name
267 ( Error.UnknownQualifier moduleName name
268 , Set.toList availableModules
269 |> Help.nearbyNames id moduleName
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