4 | import Libraries.Decidable.Equality as L
5 | import Libraries.Text.PrettyPrint.Prettyprinter
6 | import Libraries.Text.PrettyPrint.Prettyprinter.Util
7 | import Libraries.Utils.String
9 | import Libraries.Text.Distance.Levenshtein as Distance
11 | import public Core.Name.Namespace
17 | data UserName : Type where
18 | Basic : String -> UserName
19 | Field : String -> UserName
20 | Underscore : UserName
27 | mkUserName : String -> UserName
28 | mkUserName "_" = Underscore
29 | mkUserName str with (strM str)
30 | mkUserName _ | StrCons '.' n = Field n
31 | mkUserName str | _ = Basic str
36 | data Name : Type where
37 | NS : Namespace -> Name -> Name
38 | UN : UserName -> Name
39 | MN : String -> Int -> Name
40 | PV : Name -> Int -> Name
41 | DN : String -> Name -> Name
42 | Nested : (Int, Int) -> Name -> Name
43 | CaseBlock : String -> Int -> Name
44 | WithBlock : String -> Int -> Name
45 | Resolved : Int -> Name
50 | mkNamespacedName : Maybe Namespace -> UserName -> Name
51 | mkNamespacedName Nothing nm = UN nm
52 | mkNamespacedName (Just ns) nm = NS ns (UN nm)
59 | matches : Name -> Name -> Bool
60 | matches (NS ns _) (NS cns _) = isApproximationOf ns cns
68 | asName : ModuleIdent ->
72 | asName old new (DN s n) = DN s (asName old new n)
73 | asName old new (NS ns n)
74 | = NS (replace old new ns) n
78 | userNameRoot : Name -> Maybe UserName
79 | userNameRoot (NS _ n) = userNameRoot n
80 | userNameRoot (UN n) = Just n
81 | userNameRoot (DN _ n) = userNameRoot n
82 | userNameRoot _ = Nothing
85 | isOpChar : Char -> Bool
86 | isOpChar c = c `elem` (unpack ":!#$%&*+./<=>?@\\^|-~")
90 | isOpUserName : UserName -> Bool
91 | isOpUserName (Basic n) = fromMaybe False $
do
92 | c <- fst <$> strUncons n
95 | isOpUserName (Field _) = False
96 | isOpUserName Underscore = False
100 | isOpName : Name -> Bool
101 | isOpName = maybe False isOpUserName . userNameRoot
104 | isUnderscoreName : Name -> Bool
105 | isUnderscoreName (UN Underscore) = True
106 | isUnderscoreName (MN "_" _) = True
107 | isUnderscoreName _ = False
110 | isPatternVariable : UserName -> Bool
111 | isPatternVariable (Basic nm) = lowerFirst nm
112 | isPatternVariable (Field _) = False
113 | isPatternVariable Underscore = True
116 | isUserName : Name -> Bool
117 | isUserName (PV {}) = False
118 | isUserName (MN {}) = False
119 | isUserName (NS _ n) = isUserName n
120 | isUserName (DN _ n) = isUserName n
121 | isUserName _ = True
126 | isSourceName : Name -> Bool
127 | isSourceName (NS _ n) = isSourceName n
128 | isSourceName (UN {}) = True
129 | isSourceName (MN {}) = False
130 | isSourceName (PV n _) = isSourceName n
131 | isSourceName (DN _ n) = isSourceName n
132 | isSourceName (Nested _ n) = isSourceName n
133 | isSourceName (CaseBlock {}) = False
134 | isSourceName (WithBlock {}) = False
135 | isSourceName (Resolved {}) = False
138 | isRF : Name -> Maybe (Namespace, String)
139 | isRF (NS ns n) = map (mapFst (ns <.>)) (isRF n)
140 | isRF (UN (Field n)) = Just (emptyNS, n)
144 | isUN : Name -> Maybe (Namespace, UserName)
145 | isUN (UN un) = Just (emptyNS, un)
146 | isUN (NS ns n) = map (mapFst (ns <.>)) (isUN n)
150 | isBasic : UserName -> Maybe String
151 | isBasic (Basic str) = Just str
152 | isBasic _ = Nothing
155 | isField : UserName -> Maybe String
156 | isField (Field str) = Just str
157 | isField _ = Nothing
160 | caseFn : Name -> Bool
161 | caseFn (CaseBlock {}) = True
162 | caseFn (DN _ n) = caseFn n
163 | caseFn (NS _ n) = caseFn n
168 | displayUserName : UserName -> String
169 | displayUserName (Basic n) = n
170 | displayUserName (Field n) = n
171 | displayUserName Underscore = "_"
174 | nameRoot : Name -> String
175 | nameRoot (NS _ n) = nameRoot n
176 | nameRoot (UN n) = displayUserName n
177 | nameRoot (MN n _) = n
178 | nameRoot (PV n _) = nameRoot n
179 | nameRoot (DN _ n) = nameRoot n
180 | nameRoot (Nested _ inner) = nameRoot inner
181 | nameRoot (CaseBlock n _) = "$" ++ show n
182 | nameRoot (WithBlock n _) = "$" ++ show n
183 | nameRoot (Resolved i) = "$" ++ show i
186 | displayName : Name -> (Maybe Namespace, String)
187 | displayName (NS ns n) = mapFst (pure . maybe ns (ns <.>)) $
displayName n
188 | displayName (UN n) = (Nothing, displayUserName n)
189 | displayName (MN n _) = (Nothing, n)
190 | displayName (PV n _) = displayName n
191 | displayName (DN n _) = (Nothing, n)
192 | displayName (Nested _ n) = displayName n
193 | displayName (CaseBlock outer _) = (Nothing, "case block in " ++ show outer)
194 | displayName (WithBlock outer _) = (Nothing, "with block in " ++ show outer)
195 | displayName (Resolved i) = (Nothing, "$resolved" ++ show i)
198 | splitNS : Name -> (Namespace, Name)
199 | splitNS (NS ns nm) = mapFst (ns <.>) (splitNS nm)
200 | splitNS nm = (emptyNS, nm)
204 | dropNS : Name -> Name
205 | dropNS (NS _ n) = n
210 | dropAllNS : Name -> Name
211 | dropAllNS (NS _ n) = dropAllNS n
215 | mbApplyNS : Maybe Namespace -> Name -> Name
216 | mbApplyNS Nothing n = n
217 | mbApplyNS (Just ns) n = NS ns n
220 | isUnsafeBuiltin : Name -> Bool
221 | isUnsafeBuiltin nm = case splitNS nm of
222 | (ns, UN (Basic str)) =>
223 | (ns == builtinNS || ns == emptyNS)
224 | && any {t = List} id
225 | [ "assert_" `isPrefixOf` str
226 | , str `elem` [ "prim__believe_me", "believe_me"
227 | , "prim__crash", "idris_crash"
233 | Show UserName where
235 | show (Field n) = "." ++ n
236 | show Underscore = "_"
240 | show (NS ns n@(UN (Field _))) = show ns ++ ".(" ++ show n ++ ")"
241 | show (NS ns (UN (Basic n))) = if any isOpChar (unpack n)
242 | then "\{show ns}.(\{n})"
243 | else "\{show ns}.\{n}"
244 | show (NS ns n) = "\{show ns}.\{show n}"
245 | show (UN x) = show x
246 | show (MN x y) = "{" ++ x ++ ":" ++ show y ++ "}"
247 | show (PV n d) = "{P:" ++ show n ++ ":" ++ show d ++ "}"
248 | show (DN str n) = str
249 | show (Nested (outer, idx) inner)
250 | = show outer ++ ":" ++ show idx ++ ":" ++ show inner
251 | show (CaseBlock outer i) = "case block in " ++ outer
252 | show (WithBlock outer i) = "with block in " ++ outer
253 | show (Resolved x) = "$resolved" ++ show x
256 | [RawUN] Show UserName where
257 | showPrec d (Basic n) = showCon d "Basic " n
258 | showPrec d (Field n) = showCon d "Field " n
259 | showPrec d Underscore = "Underscore"
263 | [Raw] Show Name where
264 | showPrec d (NS ns n) = showCon d "NS" $
showArg ns ++ showArg n
265 | showPrec d (UN x) = showCon d "UN" $
showArg @{RawUN} x
266 | showPrec d (MN x y) = showCon d "MN" $
showArg x ++ showArg y
267 | showPrec d (PV n i) = showCon d "PV" $
showArg n ++ showArg i
268 | showPrec d (DN str n) = showCon d "DN" $
showArg str ++ showArg n
269 | showPrec d (Nested ij n) = showCon d "Nested" $
showArg ij ++ showArg n
270 | showPrec d (CaseBlock str i) = showCon d "CaseBlock" $
showArg str ++ showArg i
271 | showPrec d (WithBlock str i) = showCon d "WithBlock" $
showArg str ++ showArg i
272 | showPrec d (Resolved i) = showCon d "Resolved" $
showArg i
275 | Pretty Void UserName where
276 | pretty (Basic n) = pretty n
277 | pretty (Field n) = "." <+> pretty n
278 | pretty Underscore = "_"
283 | isPrettyOp : Bool -> Name -> Bool
284 | isPrettyOp b (UN nm@(Field _)) = b
285 | isPrettyOp b (UN nm@(Basic _)) = isOpUserName nm
286 | isPrettyOp b (DN str _) = isOpUserName (Basic str)
287 | isPrettyOp b nm = False
293 | prettyOp : Bool -> Name -> Doc Void
294 | prettyOp b nm = parenthesise (isPrettyOp b nm) (pretty nm)
298 | Pretty Void Name where
299 | pretty (NS ns n) = pretty ns <+> dot <+> prettyOp True n
300 | pretty (UN x) = pretty x
301 | pretty (MN x y) = braces (pretty x <+> colon <+> byShow y)
302 | pretty (PV n d) = braces (pretty 'P' <+> colon <+> pretty n <+> colon <+> byShow d)
303 | pretty (DN str _) = pretty str
304 | pretty (Nested (outer, idx) inner)
305 | = byShow outer <+> colon <+> byShow idx <+> colon <+> pretty inner
306 | pretty (CaseBlock outer _) = reflow "case block in" <++> pretty outer
307 | pretty (WithBlock outer _) = reflow "with block in" <++> pretty outer
308 | pretty (Resolved x) = pretty "$resolved" <+> pretty (show x)
312 | (==) (Basic x) (Basic y) = x == y
313 | (==) (Field x) (Field y) = x == y
314 | (==) Underscore Underscore = True
319 | (==) (NS ns n) (NS ns' n') = n == n' && ns == ns'
320 | (==) (UN x) (UN y) = x == y
321 | (==) (MN x y) (MN x' y') = y == y' && x == x'
322 | (==) (PV x y) (PV x' y') = x == x' && y == y'
323 | (==) (DN _ n) (DN _ n') = n == n'
324 | (==) (Nested x y) (Nested x' y') = x == x' && y == y'
325 | (==) (CaseBlock x y) (CaseBlock x' y') = y == y' && x == x'
326 | (==) (WithBlock x y) (WithBlock x' y') = y == y' && x == x'
327 | (==) (Resolved x) (Resolved x') = x == x'
330 | usernameTag : UserName -> Int
331 | usernameTag (Basic _) = 0
332 | usernameTag (Field _) = 2
333 | usernameTag Underscore = 3
337 | compare (Basic x) (Basic y) = compare x y
338 | compare (Field x) (Field y) = compare x y
339 | compare Underscore Underscore = EQ
340 | compare x y = compare (usernameTag x) (usernameTag y)
342 | nameTag : Name -> Int
343 | nameTag (NS {}) = 0
344 | nameTag (UN {}) = 1
345 | nameTag (MN {}) = 2
346 | nameTag (PV {}) = 3
347 | nameTag (DN {}) = 4
348 | nameTag (Nested {}) = 6
349 | nameTag (CaseBlock {}) = 7
350 | nameTag (WithBlock {}) = 8
351 | nameTag (Resolved {}) = 9
355 | compare (NS x y) (NS x' y')
356 | = case compare y y' of
362 | compare (UN x) (UN y) = compare x y
363 | compare (MN x y) (MN x' y')
364 | = case compare y y' of
368 | compare (PV x y) (PV x' y')
369 | = case compare y y' of
373 | compare (DN _ n) (DN _ n') = compare n n'
374 | compare (Nested x y) (Nested x' y')
375 | = case compare y y' of
379 | compare (CaseBlock x y) (CaseBlock x' y')
380 | = case compare y y' of
384 | compare (WithBlock x y) (WithBlock x' y')
385 | = case compare y y' of
389 | compare (Resolved x) (Resolved y) = compare x y
391 | compare x y = compare (nameTag x) (nameTag y)
395 | userNameEq : (x, y : UserName) -> Maybe (x = y)
396 | userNameEq (Basic x) (Basic y) = L.maybeCong Basic (L.maybeEq x y)
397 | userNameEq (Field x) (Field y) = L.maybeCong Field (L.maybeEq x y)
398 | userNameEq Underscore Underscore = Just Refl
399 | userNameEq _ _ = Nothing
403 | nameEq : (x : Name) -> (y : Name) -> Maybe (x = y)
404 | nameEq (NS xs x) (NS ys y) = L.maybeCong2 NS (L.maybeEq xs ys) (nameEq x y)
405 | nameEq (UN x) (UN y) = L.maybeCong UN (userNameEq x y)
406 | nameEq (MN x t) (MN x' t') = L.maybeCong2 MN (L.maybeEq x x') (L.maybeEq t t')
407 | nameEq (PV x t) (PV y t') = L.maybeCong2 PV (nameEq x y) (L.maybeEq t t')
408 | nameEq (DN x t) (DN y t') = L.maybeCong2 DN (L.maybeEq x y) (nameEq t t')
409 | nameEq (Nested x y) (Nested x' y') = L.maybeCong2 Nested (L.maybeEq x x') (nameEq y y')
410 | nameEq (CaseBlock x y) (CaseBlock x' y') = L.maybeCong2 CaseBlock (L.maybeEq x x') (L.maybeEq y y')
411 | nameEq (WithBlock x y) (WithBlock x' y') = L.maybeCong2 WithBlock (L.maybeEq x x') (L.maybeEq y y')
412 | nameEq (Resolved x) (Resolved y) = L.maybeCong Resolved (L.maybeEq x y)
413 | nameEq _ _ = Nothing
416 | namesEq : (xs, ys : List Name) -> Maybe (xs = ys)
417 | namesEq [] [] = Just Refl
418 | namesEq (x :: xs) (y :: ys) = L.maybeCong2 (::) (nameEq x y) (namesEq xs ys)
419 | namesEq _ _ = Nothing
423 | next : Name -> Name
424 | next (MN n i) = MN n (i + 1)
425 | next (UN n) = MN (show n) 0
426 | next (NS ns n) = NS ns (next n)
427 | next n = MN (show n) 0
431 | closeNamespaceDistance : Nat
432 | closeNamespaceDistance = 3
436 | closeDistance : String -> String -> IO Bool
437 | closeDistance s1 s2 = pure (!(Distance.compute s1 s2) < closeNamespaceDistance)
442 | closeMatch : (test, reference : Name) -> IO Bool
443 | closeMatch (NS pathTest nameTest) (NS pathRef nameRef)
444 | = let extractNameString = toList . (map snd . isUN >=> isBasic)
445 | unfoldedTest = unsafeUnfoldNamespace pathTest ++ extractNameString nameTest
446 | unfoldedRef = unsafeUnfoldNamespace pathRef ++ extractNameString nameRef
447 | tests : IO (List Nat) = traverse (uncurry Distance.compute) (zip unfoldedTest unfoldedRef)
448 | in map ((<= closeNamespaceDistance) . sum) tests
449 | closeMatch (UN (Basic test)) (UN (Basic ref)) = closeDistance test ref
450 | closeMatch _ _ = pure False