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
module Parser = Query_parser
module Dynamic_cost = Dynamic_cost
module Storage = Db.Storage
module Tree = Db.String_automata
module Private = struct
module Succ = Succ
module Type_parser = struct
let of_string str =
let lexbuf = Lexing.from_string str in
Ok (Type_parser.main Type_lexer.token lexbuf)
end
end
let polarities typ =
List.of_seq
@@ Seq.filter
(fun (word, _count, _) -> String.length word > 0)
(Db.Type_polarity.of_typ ~any_is_poly:false typ)
let find_types ~shard typ =
let polarities = polarities typ in
Succ.inter_of_list
@@ List.map
(fun (name, count, polarity) ->
let st_occ =
match polarity with
| Db.Type_polarity.Sign.Pos -> shard.Db.db_pos_types
| Neg -> shard.Db.db_neg_types
in
Succ.of_automatas
@@ Db.Occurences.fold
(fun occurrences st acc ->
if occurrences < count
then acc
else begin
let ts = Tree.find_star st name in
List.rev_append ts acc
end)
st_occ
[])
polarities
let find_names ~shard names =
let names = List.map String.lowercase_ascii names in
let db_names = Db.(shard.db_names) in
let candidates =
List.map
(fun name ->
match Tree.find db_names name with
| Some trie -> Succ.of_automata trie
| None -> Succ.empty)
names
in
Succ.inter_of_list candidates
let search ~shard { Query_parser.name; typ } =
match name, typ with
| _ :: _, `typ typ ->
let results_name = find_names ~shard name in
let results_typ = find_types ~shard typ in
Succ.inter results_name results_typ
| _ :: _, _ -> find_names ~shard name
| [], `typ typ -> find_types ~shard typ
| [], (`no_typ | `parse_error) -> Succ.empty
let search ~shards query =
Succ.union_of_list (List.map (fun shard -> search ~shard query) shards)
type t =
{ query : string
; packages : string list
; limit : int
}
let pretty params = Parser.(to_string @@ of_string params.query)
let match_packages ~packages { Db.Entry.pkg; _ } =
List.exists (String.equal pkg.name) packages
let match_packages ~packages results =
match packages with
| [] -> results
| _ -> Seq.filter (match_packages ~packages) results
let search ~shards params =
let query = Parser.of_string params.query in
let results = search ~shards query in
let results = Succ.to_seq results in
query, match_packages ~packages:params.packages results
module type IO = Io.S
module Make (Io : IO) = struct
module Tr = Top_results.Make (Io)
let search ~shards ?(dynamic_sort = true) params =
let limit = params.limit in
let query, results = search ~shards params in
let results = Tr.Seq.of_seq results in
if dynamic_sort
then begin
let query = Dynamic_cost.of_query query in
Tr.of_seq ~query ~limit results
end
else Tr.Seq.to_list @@ Tr.Seq.take limit results
end
module Blocking = Make (struct
type 'a t = 'a
let return x = x
let map x f = f x
let bind x f = f x
end)