on 577fc17 help sign in
86 lines 3.1 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.Type as Type
11import qualified AST.Variable as Var
12import Transform.Canonicalize.Environment as Env
14variable :: Environment -> String -> Canonicalizer String Var.Canonical
15variable env var =
16 case modul of
17 Just ms@(m:_)
18 | m == "Native" -> Env.using (Var.Canonical home name)
19 where
20 home = Var.Module (List.intercalate "." ms)
22 _ -> case Map.lookup var (_values env) of
23 Just [v] -> Env.using v
24 Just vs -> preferLocals "variable" vs var
25 Nothing -> notFound "variable" (Map.keys (_values env)) var
26 where
27 (modul, name) = case Help.splitDots var of
28 [x] -> (Nothing, x)
29 xs -> (Just (init xs), last xs)
31tvar :: Environment -> String
32 -> Canonicalizer String (Either Var.Canonical (Var.Canonical, [String], Type.CanonicalType))
33tvar env var =
34 case adts ++ aliases of
35 [] -> notFound "type" (Map.keys (_adts env) ++ Map.keys (_aliases env)) var
36 [v] -> found extract v
37 vs -> preferLocals' extract "type" vs var
38 where
39 adts = map Left . fromMaybe [] $ Map.lookup var (_adts env)
40 aliases = map Right . fromMaybe [] $ Map.lookup var (_aliases env)
42 extract value =
43 case value of
44 Left v -> v
45 Right (v,_,_) -> v
47pvar :: Environment -> String -> Canonicalizer String Var.Canonical
48pvar env var =
49 case Map.lookup var (_patterns env) of
50 Just [v] -> Env.using v
51 Just vs -> preferLocals "pattern" vs var
52 Nothing -> notFound "pattern" (Map.keys (_patterns env)) var
54found :: (a -> Var.Canonical) -> a -> Canonicalizer String a
55found extract v = do
56 _ <- Env.using (extract v)
57 return v
59notFound :: String -> [String] -> String -> Canonicalizer String a
60notFound kind possibilities var =
61 throwError $ "Could not find " ++ kind ++ " '" ++ var ++ "'." ++ msg
62 where
63 matches = filter (List.isInfixOf var) possibilities
64 msg = if null matches then "" else
65 "\nClose matches include: " ++ List.intercalate ", " matches
67preferLocals :: String -> [Var.Canonical] -> String -> Canonicalizer String Var.Canonical
68preferLocals = preferLocals' id
70preferLocals' :: (a -> Var.Canonical) -> String -> [a] -> String -> Canonicalizer String a
71preferLocals' extract kind possibilities var =
72 case filter (isLocal . extract) possibilities of
73 [] -> ambiguous possibilities
74 [v] -> found extract v
75 locals -> ambiguous locals
76 where
77 isLocal :: Var.Canonical -> Bool
78 isLocal (Var.Canonical home _) = home == Var.Local
80 ambiguous possibleVars =
81 throwError msg
82 where
83 vars = map (Var.toString . extract) possibleVars
84 msg = "Ambiguous usage of " ++ kind ++ " '" ++ var ++ "'.\n" ++
85 " Disambiguate between: " ++ List.intercalate ", " vars