-
Notifications
You must be signed in to change notification settings - Fork 374
/
String.idr
706 lines (650 loc) · 28.3 KB
/
String.idr
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
module Idris.Doc.String
import Core.Context
import Core.Context.Log
import Core.Core
import Core.Env
import Core.TT
import Core.TT.Traversals
import Idris.Doc.Display
import Idris.Pretty
import Idris.REPL.Opts
import Idris.Resugar
import Idris.Syntax
import Idris.Syntax.Views
import TTImp.TTImp
import TTImp.TTImp.Functor
import TTImp.Elab.Prim
import Data.List
import Data.List1
import Data.Maybe
import Data.String
import Libraries.Data.ANameMap
import Libraries.Data.NameMap
import Libraries.Data.SortedSet
import Libraries.Data.SortedMap
import Libraries.Data.StringMap as S
import Libraries.Data.String.Extra
import Libraries.Data.WithDefault
import public Libraries.Text.PrettyPrint.Prettyprinter
import public Libraries.Text.PrettyPrint.Prettyprinter.Util
import Parser.Lexer.Source
import public Idris.Doc.Annotations
import Idris.Doc.Keywords
import Idris.Doc.Brackets
%default covering
-- Add a doc string for a name in the current namespace
export
addDocString : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
Name -> String ->
Core ()
addDocString n_in doc
= do n <- inCurrentNS n_in
log "doc.record" 50 $
"Adding doc for " ++ show n_in ++ " (aka " ++ show n ++ " in current NS)"
update Syn { defDocstrings $= addName n doc,
saveDocstrings $= insert n () }
-- Add a doc string for a name, in an extended namespace (e.g. for
-- record getters)
export
addDocStringNS : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
Namespace -> Name -> String ->
Core ()
addDocStringNS ns n_in doc
= do n <- inCurrentNS n_in
let n' = case n of
NS old root => NS (old <.> ns) root
root => NS ns root
update Syn { defDocstrings $= addName n' doc,
saveDocstrings $= insert n' () }
prettyName : Name -> Doc IdrisDocAnn
prettyName n =
case userNameRoot n of
-- shouldn't happen: we only show UN anyways...
Nothing => pretty0 (nameRoot n)
Just un => if isOpUserName un then parens (pretty0 un) else pretty0 un
prettyKindedName : Maybe String -> Doc IdrisDocAnn -> Doc IdrisDocAnn
prettyKindedName Nothing nm = nm
prettyKindedName (Just kw) nm
= annotate (Syntax Keyword) (pretty0 kw) <++> nm
export
prettyType : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
(IdrisSyntax -> ann) -> ClosedTerm -> Core (Doc ann)
prettyType syn ty = do
defs <- get Ctxt
ty <- normaliseHoles defs [] ty
ty <- toFullNames ty
ty <- resugar [] ty
pure (prettyBy syn ty)
||| Look up implementations
getImplDocs : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
(keep : Term [] -> Core Bool) ->
Core (List (Doc IdrisDocAnn))
getImplDocs keep
= do defs <- get Ctxt
docss <- for (concat $ values $ typeHints defs) $ \ (impl, _) =>
do Just def <- lookupCtxtExact impl (gamma defs)
| _ => pure []
-- Only keep things that look like implementations.
-- i.e. get rid of data constructors
let Just Func = defNameType (definition def)
| _ => pure []
-- Check that the type mentions the name of interest
ty <- toFullNames !(normaliseHoles defs [] (type def))
True <- keep ty
| False => pure []
ty <- resugar [] ty
pure [annotate (Decl impl) $ prettyBy Syntax ty]
pure $ case concat docss of
[] => []
[doc] => [header "Hint" <++> annotate Declarations doc]
docs => [vcat [header "Hints"
, annotate Declarations $
vcat $ map (indent 2) docs]]
||| Look up implementations corresponding to the named type
getHintsForType : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
Name -> Core (List (Doc IdrisDocAnn))
getHintsForType nty
= do log "doc.data" 10 $ "Looking at \{show nty}"
getImplDocs $ \ ty =>
do let nms = allGlobals ty
log "doc.data" 10 $ unlines
[ "Candidate: " ++ show ty
, "Containing names: " ++ show nms
]
pure $ isJust (lookup nty nms)
||| Look up implementations corresponding to the primitive type
getHintsForPrimitive : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
Constant -> Core (List (Doc IdrisDocAnn))
getHintsForPrimitive c
= do log "doc.data" 10 $ "Looking at \{show c}"
getImplDocs $ \ ty =>
do let nms = allConstants ty
log "doc.data" 10 $ unlines
[ "Candidate: " ++ show ty
, "Containing constants: " ++ show nms
]
pure $ contains c nms
export
getDocsForPrimitive : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
Constant -> Core (Doc IdrisDocAnn)
getDocsForPrimitive constant = do
let (_, type) = checkPrim EmptyFC constant
let typeString = prettyBy Syntax constant
<++> colon
<++> prettyBy Syntax !(resugar [] type)
hintsDoc <- getHintsForPrimitive constant
pure $ vcat $ typeString
:: indent 2 (primDoc constant)
:: hintsDoc
where
primTyDoc : PrimType -> Doc IdrisDocAnn
primTyDoc IntType = "Primitive type of bounded signed integers (backend dependent size)"
primTyDoc Int8Type = "Primitive type of 8 bits signed integers"
primTyDoc Int16Type = "Primitive type of 16 bits signed integers"
primTyDoc Int32Type = "Primitive type of 32 bits signed integers"
primTyDoc Int64Type = "Primitive type of 64 bits signed integers"
primTyDoc IntegerType = "Primitive type of unbounded signed integers"
primTyDoc Bits8Type = "Primitive type of 8 bits unsigned integers"
primTyDoc Bits16Type = "Primitive type of 16 bits unsigned integers"
primTyDoc Bits32Type = "Primitive type of 32 bits unsigned integers"
primTyDoc Bits64Type = "Primitive type of 64 bits unsigned integers"
primTyDoc StringType = "Primitive type of strings"
primTyDoc CharType = "Primitive type of characters"
primTyDoc DoubleType = "Primitive type of double-precision floating-points"
primTyDoc WorldType = "Primitive type of tokens for IO actions"
primDoc : Constant -> Doc IdrisDocAnn
primDoc (I i) = "Primitive signed int value (backend-dependent precision)"
primDoc (I8 i) = "Primitive signed 8 bits value"
primDoc (I16 i) = "Primitive signed 16 bits value"
primDoc (I32 i) = "Primitive signed 32 bits value"
primDoc (I64 i) = "Primitive signed 64 bits value"
primDoc (BI i) = "Primitive unsigned int value (backend-dependent precision)"
primDoc (B8 i) = "Primitive unsigned 8 bits value"
primDoc (B16 i) = "Primitive unsigned 16 bits value"
primDoc (B32 i) = "Primitive unsigned 32 bits value"
primDoc (B64 i) = "Primitive unsigned 64 bits value"
primDoc (Str s) = "Primitive string value"
primDoc (Ch c) = "Primitive character value"
primDoc (Db d) = "Primitive double value"
primDoc (PrT t) = primTyDoc t
primDoc WorldVal = "Primitive token for IO actions"
public export
data Config : Type where
||| Configuration of the printer for a name
||| @ showType Do we show the type?
||| @ longNames Do we print qualified names?
||| @ dropFirst Do we drop the first argument in the type?
||| @ getTotality Do we print the totality status of the function?
MkConfig : {default True showType : Bool} ->
{default True longNames : Bool} ->
{default False dropFirst : Bool} ->
{default True getTotality : Bool} ->
Config
||| Printer configuration for interface methods
||| * longNames turned off for interface methods because the namespace is
||| already spelt out for the interface itself
||| * dropFirst turned on for interface methods because the first argument
||| is always the interface constraint
||| * totality turned off for interface methods because the methods themselves
||| are just projections out of a record and so are total
export
methodsConfig : Config
methodsConfig
= MkConfig {showType = True}
{longNames = False}
{dropFirst = True}
{getTotality = False}
export
shortNamesConfig : Config
shortNamesConfig
= MkConfig {showType = True}
{longNames = False}
{dropFirst = False}
{getTotality = True}
export
justUserDoc : Config
justUserDoc
= MkConfig {showType = False}
{longNames = False}
{dropFirst = True}
{getTotality = False}
export
getDocsForName : {auto o : Ref ROpts REPLOpts} ->
{auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
FC -> Name -> Config -> Core (Doc IdrisDocAnn)
getDocsForName fc n config
= do syn <- get Syn
defs <- get Ctxt
let extra = case nameRoot n of
"-" => [NS numNS (UN $ Basic "negate")]
_ => []
resolved <- lookupCtxtName n (gamma defs)
let all@(_ :: _) = extra ++ map fst resolved
| _ => undefinedName fc n
let ns@(_ :: _) = concatMap (\n => lookupName n (defDocstrings syn)) all
| [] => pure emptyDoc
docs <- traverse (showDoc config) ns
pure $ vcat docs
where
showDoc : Config -> (Name, String) -> Core (Doc IdrisDocAnn)
reflowDoc : String -> List (Doc IdrisDocAnn)
reflowDoc str = map (indent 2 . pretty0) (lines str)
showTotal : Totality -> Maybe (Doc IdrisDocAnn)
showTotal tot
= case isTerminating tot of
Unchecked => Nothing
_ => pure (header "Totality" <++> annotate (Syntax Keyword) (pretty0 tot))
showVisible : Visibility -> Doc IdrisDocAnn
showVisible vis = header "Visibility" <++> annotate (Syntax Keyword) (pretty0 vis)
getDConDoc : {default True showType : Bool} -> Name -> Core (Doc IdrisDocAnn)
getDConDoc con
= do defs <- get Ctxt
Just def <- lookupCtxtExact con (gamma defs)
-- should never happen, since we know that the DCon exists:
| Nothing => pure Empty
syn <- get Syn
ty <- prettyType Syntax (type def)
let conWithTypeDoc
= annotate (Decl con)
$ ifThenElse showType
(hsep [dCon con (prettyName con), colon, ty])
(dCon con (prettyName con))
case lookupName con (defDocstrings syn) of
[(n, "")] => pure conWithTypeDoc
[(n, str)] => pure $ vcat
[ conWithTypeDoc
, annotate DocStringBody
$ annotate UserDocString
$ vcat $ reflowDoc str
]
_ => pure conWithTypeDoc
||| The name corresponds to an implementation, typeset its type accordingly
getImplDoc : Name -> Core (List (Doc IdrisDocAnn))
getImplDoc n
= do defs <- get Ctxt
Just def <- lookupCtxtExact n (gamma defs)
| Nothing => pure []
ty <- prettyType Syntax (type def)
pure [annotate (Decl n) ty]
getMethDoc : Method -> Core (List (Doc IdrisDocAnn))
getMethDoc meth
= do syn <- get Syn
let [nstr] = lookupName meth.name (defDocstrings syn)
| _ => pure []
pure <$> showDoc methodsConfig nstr
getInfixDoc : Name -> Core (List (Doc IdrisDocAnn))
getInfixDoc n
= let names = lookupName (UN $ Basic $ nameRoot n) (infixes !(get Syn))
in pure $ map printName names
where
printName : (Name, FC, Fixity, Nat) -> (Doc IdrisDocAnn)
printName (name, loc, fixity, assoc) =
-- todo, change display as "infix operator (++)
hsep
[ pretty0 (show fixity)
, "operator,"
, "level"
, pretty0 (show assoc)
]
getPrefixDoc : Name -> Core (List (Doc IdrisDocAnn))
getPrefixDoc n
= let names = lookupName (UN $ Basic $ nameRoot n) (prefixes !(get Syn))
in pure $ map printPrefixName names
where
printPrefixName : (Name, FC, Nat) -> Doc IdrisDocAnn
printPrefixName (_, _, assoc) = "prefix operator, level" <++> pretty0 (show assoc)
getFixityDoc : Name -> Core (List (Doc IdrisDocAnn))
getFixityDoc n =
pure $ case toList !(getInfixDoc n) ++ toList !(getPrefixDoc n) of
[] => []
[f] => [header "Fixity Declaration" <++> f]
fs => [header "Fixity Declarations" <+> Line <+>
indent 2 (vcat fs)]
getIFaceDoc : (Name, IFaceInfo) -> Core (Doc IdrisDocAnn)
getIFaceDoc (n, iface)
= do let params =
case params iface of
[] => []
ps => [hsep (header "Parameters" :: punctuate comma (map pretty0 ps))]
let constraints =
case !(traverse (pterm . map defaultKindedName) (parents iface)) of
[] => []
ps => [hsep (header "Constraints" :: punctuate comma (map (prettyBy Syntax) ps))]
icon <- do cName <- toFullNames (iconstructor iface)
case dropNS cName of
UN{} => do doc <- getDConDoc {showType = False} cName
pure $ [header "Constructor" <++> annotate Declarations doc]
_ => pure [] -- machine inserted
mdocs <- traverse getMethDoc (methods iface)
let meths = case concat mdocs of
[] => []
docs => [vcat [header "Methods", annotate Declarations $ vcat $ map (indent 2) docs]]
sd <- getSearchData fc False n
idocs <- case hintGroups sd of
[] => pure (the (List (List (Doc IdrisDocAnn))) [])
((_, tophs) :: _) => traverse getImplDoc tophs
let insts = case concat idocs of
[] => []
[doc] => [header "Implementation" <++> annotate Declarations doc]
docs => [vcat [header "Implementations"
, annotate Declarations $ vcat $ map (indent 2) docs]]
pure (vcat (params ++ constraints ++ icon ++ meths ++ insts))
getFieldDoc : Name -> Core (Doc IdrisDocAnn)
getFieldDoc nm
= do syn <- get Syn
defs <- get Ctxt
Just def <- lookupCtxtExact nm (gamma defs)
-- should never happen, since we know that the DCon exists:
| Nothing => pure Empty
ty <- prettyType Syntax (type def)
let projDecl = annotate (Decl nm) $
reAnnotate Syntax (prettyRig def.multiplicity) <+> hsep
[ fun nm (prettyName nm), colon, ty ]
case lookupName nm (defDocstrings syn) of
[(_, "")] => pure projDecl
[(_, str)] =>
pure $ vcat [ projDecl
, annotate DocStringBody
$ annotate UserDocString
$ vcat $ reflowDoc str
]
_ => pure projDecl
getFieldsDoc : Name -> Core (Maybe (Doc IdrisDocAnn))
getFieldsDoc recName
= do let (Just ns, n) = displayName recName
| _ => pure Nothing
let recNS = ns <.> mkNamespace n
defs <- get Ctxt
let fields = getFieldNames (gamma defs) recNS
case fields of
[] => pure Nothing
[proj] => pure $ Just $ header "Projection" <++> annotate Declarations !(getFieldDoc proj)
projs => pure $ Just $ vcat
[ header "Projections"
, annotate Declarations $ vcat $
map (indent 2) $ !(traverse getFieldDoc projs)
]
getExtra : Name -> GlobalDef -> Core (Maybe String, List (Doc IdrisDocAnn))
getExtra n d = do
do syn <- get Syn
let [] = lookupName n (ifaces syn)
| [ifacedata] => (Just "interface",) . pure <$> getIFaceDoc ifacedata
| _ => pure (Nothing, []) -- shouldn't happen, we've resolved ambiguity by now
case definition d of
PMDef _ _ _ _ _ => pure ( Nothing
, catMaybes [ showTotal (totality d)
, pure (showVisible (collapseDefault $ visibility d))])
TCon _ _ _ _ _ _ cons _ =>
do let tot = catMaybes [ showTotal (totality d)
, pure (showVisible (collapseDefault $ visibility d))]
cdocs <- traverse (getDConDoc <=< toFullNames) cons
cdoc <- case cdocs of
[] => pure (Just "data", [])
[doc] =>
let cdoc = header "Constructor" <++> annotate Declarations doc in
case !(getFieldsDoc n) of
Nothing => pure (Just "data", [cdoc])
Just fs => pure (Just "record", cdoc :: [fs])
docs => pure (Just "data"
, [vcat [header "Constructors"
, annotate Declarations $
vcat $ map (indent 2) docs]])
idoc <- getHintsForType n
pure (map (\ cons => tot ++ cons ++ idoc) cdoc)
_ => pure (Nothing, [])
showDoc (MkConfig {showType, longNames, dropFirst, getTotality}) (n, str)
= do defs <- get Ctxt
Just def <- lookupCtxtExact n (gamma defs)
| Nothing => undefinedName fc n
-- First get the extra stuff because this also tells us whether a
-- definition is `data`, `record`, or `interface`.
(typ, extra) <- ifThenElse getTotality
(getExtra n def)
(pure (Nothing, []))
-- Then form the type declaration
ty <- resugar [] =<< normaliseHoles defs [] (type def)
-- when printing e.g. interface methods there is no point in
-- repeating the interface's name
let ty = ifThenElse (not dropFirst) ty $ case ty of
PPi _ _ AutoImplicit _ _ sc => sc
_ => ty
nm <- aliasName n
let prig = reAnnotate Syntax $ prettyRig def.multiplicity
let cat = showCategory Syntax def
let nm = prettyKindedName typ $ cat
$ ifThenElse longNames (pretty0 (show nm)) (prettyName nm)
let deprecated = if Context.Deprecate `elem` def.flags
then annotate Deprecation "=DEPRECATED=" <+> line else emptyDoc
let docDecl = deprecated
<+> annotate (Decl n) (hsep [prig <+> nm, colon, prettyBy Syntax ty])
-- Finally add the user-provided docstring
let docText = let docs = reflowDoc str in
annotate UserDocString (vcat docs)
<$ guard (not $ null docs)
fixes <- getFixityDoc n
let docBody =
let docs = maybe id (::) docText
$ map (indent 2) (extra ++ fixes)
in annotate DocStringBody
(concatWith (\l, r => l <+> hardline <+> r) docs)
<$ guard (not (null docs))
let maybeDocDecl = [docDecl | showType]
pure . vcat . catMaybes $ maybeDocDecl :: (map Just $ docBody)
export
getDocsForImplementation :
{auto s : Ref Syn SyntaxInfo} ->
{auto c : Ref Ctxt Defs} ->
PTerm -> Core (Maybe (Doc IdrisSyntax))
getDocsForImplementation t = do
-- the term better be of the shape (I e1 e2 e3) where I is a name
let (PRef fc intf, args) = getFnArgs id t
| _ => pure Nothing
-- That name (I) better be the name of an interface
syn <- get Syn
-- Important: we shadow intf with the fully qualified version returned by lookupName
let [(intf, _)] = lookupName intf (ifaces syn)
| _ => pure Nothing
-- Now lookup the declared implementations for that interface
-- For now we only look at the top list
((_, tophs) :: _) <- hintGroups <$> getSearchData fc False intf
| _ => pure Nothing
defs <- get Ctxt
impls <- map catMaybes $ for tophs $ \ hint => do
-- get the return type of all the candidate hints
Just (ix, def) <- lookupCtxtExactI hint (gamma defs)
| Nothing => pure Nothing
ty <- resugar [] =<< normaliseHoles defs [] (type def)
let (_, retTy) = underPis ty
-- try to see whether it approximates what we are looking for
-- we throw the head away because it'll be the interface name (I)
let (_, cargs) = getFnArgs defaultKindedName retTy
bs <- for (zip args cargs) $ \ (arg, carg) => do
-- For now we only compare the heads of the arguments because we expect
-- we are interested in implementations of the form
-- Eq (List a), Functor (Vect n), etc.
-- In the future we could be more discriminating and make sure we only
-- retain implementations whose type is fully compatible.
-- TODO: check the Args have the same shape before unArgging?
let ((PRef fc hd, _), (PRef _ chd, _)) = ( getFnArgs id (unArg arg), getFnArgs defaultKindedName (unArg carg))
| ((PPrimVal _ c, _), (PPrimVal _ c', _)) => pure (c == c')
| ((PType _, _), (PType _, _)) => pure True
| _ => pure False
-- if the names match on the nose we can readily say True
let False = dropNS hd == dropNS (fullName chd)
| True => pure True
-- otherwise we check hd is unknown in which case we're happy to
-- declare it to be a placeholder name and that it could possibly
-- unify e.g. a & b in (List a) vs. (List b)
existing <- lookupCtxtName hd (gamma defs)
log "doc.implementation" 50 $ unwords
[ "Mismatch between \{show hd} and \{show chd},"
, "checking whether \{show hd} exists:"
, "\{show $ length existing} candidates"
]
let [] = existing
| _ => pure False
-- If the name starts with an uppercase letter it's probably a misspelt constructor name
whenJust ((isUN >=> (isBasic . snd) >=> strUncons >=> (guard . isUpper . fst)) hd) $ \ _ =>
undefinedName fc hd
pure True
-- all arguments better be valid approximations
let True = all id bs
| False => pure Nothing
pure (Just (hint, ix, def))
case impls of
[] => pure $ Just $ "Could not find an implementation for" <++> pretty0 (show t) --hack
_ => do ds <- traverse (displayImpl defs) impls
pure $ Just $ vcat ds
export
getDocsForPTerm : {auto o : Ref ROpts REPLOpts} ->
{auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
PTerm -> Core (Doc IdrisDocAnn)
getDocsForPTerm (PRef fc name) = getDocsForName fc name MkConfig
getDocsForPTerm (PPrimVal _ c) = getDocsForPrimitive c
getDocsForPTerm (PType _) = pure $ vcat
[ "Type : Type"
, indent 2 "The type of all types is Type. The type of Type is Type."
]
getDocsForPTerm (PString _ _ _) = pure $ vcat
[ "String Literal"
, indent 2 "Desugars to a fromString call"
]
getDocsForPTerm (PList _ _ _) = pure $ vcat
[ "List Literal"
, indent 2 "Desugars to (::) and Nil"
]
getDocsForPTerm (PSnocList _ _ _) = pure $ vcat
[ "SnocList Literal"
, indent 2 "Desugars to (:<) and Lin"
]
getDocsForPTerm (PPair _ _ _) = pure $ vcat
[ "Pair Literal"
, indent 2 "Desugars to MkPair or Pair"
]
getDocsForPTerm (PDPair _ _ _ _ _) = pure $ vcat
[ "Dependant Pair Literal"
, indent 2 "Desugars to MkDPair or DPair"
]
getDocsForPTerm (PUnit _) = pure $ vcat
[ "Unit Literal"
, indent 2 "Desugars to MkUnit or Unit"
]
getDocsForPTerm (PUnquote _ _) = pure $ vcat $
header "Unquotes" :: ""
:: map (indent 2) [
"""
Unquotes allows us to use TTImp expressions inside a quoted expression.
This is useful when we want to add some computed TTImp while building up
complex expressions.
```idris
module Quote
import Language.Reflection
foo : TTImp -> TTImp
foo expr = `(either ~(expr) x y)
```
"""]
getDocsForPTerm (PDelayed _ LLazy _) = pure $ vcat $
header "Laziness annotation" :: ""
:: map (indent 2) [
"""
Indicates that the values of the type should not be computed until absolutely
necessary.
Also causes the compiler to automatically insert Delay/Force calls
respectively wherever a computation can be postponed and where a value is
necessary. This can be disabled using the `%auto_lazy off` pragma.
"""
]
getDocsForPTerm (PDelayed _ LInf _) = pure $ vcat $
header "Codata (infinite data type) annotation" :: ""
:: map (indent 2) [
"""
Indicates that the data type may be potentially infinite, e.g. Data.Stream.
If the data type IS infinite, it has to be productive, i.e. there has to be at
least one non-empty, finite prefix of the type.
Also causes the compiler to automatically insert Delay/Force calls
respectively wherever the next part of a potentially infinite structure
occurs, and where we need to look under the next finite prefix of the
structure. This can be disabled using the `%auto_lazy off` pragma.
"""
]
getDocsForPTerm (PDelay _ _) = pure $ vcat $
header "Laziness compiler primitive" :: ""
:: map (indent 2) [
"""
For `Lazy` types: postpones the computation until a `Force` requires its
result.
For `Inf` types: does not try to deconstruct the next part of the codata
(potentially infinite data structure).
Automatically inserted by the compiler unless `%auto_lazy off` is set.
"""
]
getDocsForPTerm (PForce _ _) = pure $ vcat $
header "Laziness compiler primitive" :: ""
:: map (indent 2) [
"""
For `Lazy` types: requires the result of a postponed calculation to be
evaluated (see `Delay`).
For `Inf` types: deconstructs the next part of the codata (potentially
infinite data structure).
Automatically inserted by the compiler unless `%auto_lazy off` is set.
"""
]
getDocsForPTerm pterm = pure $ "Docs not implemented for" <++> pretty0 (show pterm) <++> "yet"
export
getDocs : {auto o : Ref ROpts REPLOpts} ->
{auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
DocDirective -> Core (Doc IdrisDocAnn)
getDocs (APTerm ptm) = getDocsForPTerm ptm
getDocs (Symbol k) = pure $ getDocsForSymbol k
getDocs (Bracket bracket) = pure $ getDocsForBracket bracket
getDocs (Keyword k) = pure $ getDocsForKeyword k
getDocs (AModule mod) = do
syn <- get Syn
let Just modDoc = lookup mod (modDocstrings syn)
| _ => throw (ModuleNotFound replFC mod)
pure (pretty0 modDoc)
summarise : {auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
Name -> Core (Doc IdrisDocAnn)
summarise n -- n is fully qualified
= do defs <- get Ctxt
Just def <- lookupCtxtExact n (gamma defs)
| _ => pure ""
ty <- prettyType Syntax (type def)
pure $ reAnnotate Syntax (prettyRig def.multiplicity)
<+> hsep [ showCategory Syntax def (prettyName n)
, colon, hang 0 ty
]
-- Display all the exported names in the given namespace
export
getContents : {auto o : Ref ROpts REPLOpts} ->
{auto c : Ref Ctxt Defs} ->
{auto s : Ref Syn SyntaxInfo} ->
Namespace -> Core (Doc IdrisDocAnn)
getContents ns
= -- Get all the names, filter by any that match the given namespace
-- and are visible, then display with their type
do defs <- get Ctxt
ns <- allNames (gamma defs)
let allNs = filter inNS ns
allNs <- filterM (visible defs) allNs
vsep <$> traverse summarise (sort allNs)
where
visible : Defs -> Name -> Core Bool
visible defs n
= do Just def <- lookupCtxtExact n (gamma defs)
| Nothing => pure False
pure (collapseDefault (visibility def) /= Private)
inNS : Name -> Bool
inNS (NS xns (UN _)) = ns `isParentOf` xns
inNS _ = False