on d87affe help sign in
95 lines 3.3 kB history raw
1{-# OPTIONS_GHC -Wall #-}
2module Transform.Canonicalize.Variable where
4import Control.Monad.Error
5import qualified Data.List as List
6import qualified Data.Map as Map
7import Data.Maybe (fromMaybe)
9import AST.Helpers as Help
10import qualified AST.Module as Module
11import qualified AST.Type as Type
12import qualified AST.Variable as Var
13import Transform.Canonicalize.Environment as Env
15variable :: Environment -> String -> Canonicalizer String Var.Canonical
16variable env var =
17 case modul of
18 Just name
19 | Module.nameIsNative name ->
20 Env.using (Var.Canonical (Var.Module name) varName)
22 _ ->
23 case Map.lookup var (_values env) of
24 Just [v] -> Env.using v
25 Just vs -> preferLocals env "variable" vs var
26 Nothing -> notFound "variable" (Map.keys (_values env)) var
27 where
28 (modul, varName) =
29 case Help.splitDots var of
30 [x] -> (Nothing, x)
31 xs -> (Just (init xs), last xs)
33tvar :: Environment -> String
34 -> Canonicalizer String (Either Var.Canonical (Var.Canonical, [String], Type.CanonicalType))
35tvar env var =
36 case adts ++ aliases of
37 [] -> notFound "type" (Map.keys (_adts env) ++ Map.keys (_aliases env)) var
38 [v] -> found extract v
39 vs -> preferLocals' env extract "type" vs var
40 where
41 adts = map Left . fromMaybe [] $ Map.lookup var (_adts env)
42 aliases = map Right . fromMaybe [] $ Map.lookup var (_aliases env)
44 extract value =
45 case value of
46 Left v -> v
47 Right (v,_,_) -> v
49pvar :: Environment -> String -> Canonicalizer String Var.Canonical
50pvar env var =
51 case Map.lookup var (_patterns env) of
52 Just [v] -> Env.using v
53 Just vs -> preferLocals env "pattern" vs var
54 Nothing -> notFound "pattern" (Map.keys (_patterns env)) var
56found :: (a -> Var.Canonical) -> a -> Canonicalizer String a
57found extract v = do
58 _ <- Env.using (extract v)
59 return v
61notFound :: String -> [String] -> String -> Canonicalizer String a
62notFound kind possibilities var =
63 throwError $ "Could not find " ++ kind ++ " '" ++ var ++ "'." ++ msg
64 where
65 matches = filter (List.isInfixOf var) possibilities
66 msg = if null matches then "" else
67 "\nClose matches include: " ++ List.intercalate ", " matches
69preferLocals :: Environment -> String -> [Var.Canonical] -> String
70 -> Canonicalizer String Var.Canonical
71preferLocals env = preferLocals' env id
73preferLocals' :: Environment -> (a -> Var.Canonical) -> String -> [a] -> String
74 -> Canonicalizer String a
75preferLocals' env extract kind possibilities var =
76 case filter (isLocal . extract) possibilities of
77 [] -> ambiguous possibilities
78 [v] -> found extract v
79 locals -> ambiguous locals
80 where
81 isLocal :: Var.Canonical -> Bool
82 isLocal (Var.Canonical home _) =
83 case home of
84 Var.Local -> True
85 Var.BuiltIn -> False
86 Var.Module name ->
87 name == Env._home env
89 ambiguous possibleVars =
90 throwError msg
91 where
92 vars = map (Var.toString . extract) possibleVars
93 msg = "Ambiguous usage of " ++ kind ++ " '" ++ var ++ "'.\n" ++
94 " Disambiguate between: " ++ List.intercalate ", " vars