-
Notifications
You must be signed in to change notification settings - Fork 0
/
scope.hs
62 lines (50 loc) · 2.13 KB
/
scope.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
module Scope where
import Data.Hashable
import qualified Data.Set as Set
import qualified Text.Megaparsec as P
import Data.List
import Data.Maybe
import Lev
import Debug.Trace
data Scope = Scope{getElems :: Set.Set StringPos, getParent :: Maybe Scope}
existsIn str (Scope set par) =
(str `Set.member` set) ||
case par of
Just pset -> str `existsIn` pset
Nothing -> False
instance Show Scope where
show (Scope set par) = show set ++ " -> " ++ maybeScope where
maybeScope =
case par of
Just sc@Scope{} -> show sc
Nothing -> "{}"
data StringPos = StringPos String P.SourcePos
instance Show StringPos where
show (StringPos s _) = s
instance Eq StringPos where
(StringPos a _) == (StringPos b _) = a == b
instance Ord StringPos where
(StringPos a _) <= (StringPos b _) = hash a <= hash b
getAllElems :: Scope -> Set.Set StringPos
getAllElems sc = maybe (getElems sc) (\nsc -> getElems sc `Set.union` getAllElems nsc) (getParent sc)
-- existence checking function
exists id sc =
if id `existsIn` sc then
Right ()
else
case getStr id of
[a] -> Left $ showPos (getPos id) ++ "\n" ++ "No definition for " ++ [a] ++ " found"
_ ->
case closeOnes of
[] -> Left $ showPos (getPos id) ++ "\n" ++ "No definition for '" ++ getStr id ++ "' found"
[a] -> Left $ showPos (getPos id) ++ "\n" ++ "No definition for '" ++ getStr id ++ "' found\n" ++
"Maybe, you meant " ++ show a
_ -> Left $ showPos (getPos id) ++ "\n" ++ "No definition for '" ++ getStr id ++ "' found\n" ++
"Perhaps, you meant one of " ++ intercalate ", " closeOnes
where
getPos (StringPos _ pos) = pos
getStr (StringPos str _) = str
closeOnes = closest 3 (getStr id) $ map getStr $ Set.toList $ getAllElems sc
-- showing a position
showPos (P.SourcePos s ln cn) =
"In file: " ++ s ++ ", at line: " ++ tail (dropWhile (/= ' ') (show ln)) ++ ", at colounm: " ++ tail (dropWhile (/= ' ') (show cn))