Skip to content

Commit fcd430a

Browse files
committed
Add query.d
1 parent d9e20c7 commit fcd430a

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

query.d

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/++ Query system that implements Roam queries. +/
2+
module query;
3+
import interp;
4+
debug import std.stdio;
5+
6+
// Unoptimized function to calculate matches for a set of
7+
// words
8+
// This should be replaced by something faster.
9+
// For instance, a regex library, that scans once, instead of once
10+
struct DumbMatcher(BitType) {
11+
string[] search_terms;
12+
this(string[] terms) {
13+
search_terms = terms;
14+
}
15+
BitType match(string str) {
16+
import std.algorithm.searching : canFind;
17+
BitType result;
18+
debug writeln("Query " ~ str);
19+
for (int i = 0; i < search_terms.length; ++i) {
20+
auto term = search_terms[i];
21+
if (canFind(str, term)) {
22+
debug writeln("Matched with " ~ term);
23+
result |= 1 << i;
24+
}
25+
}
26+
return result;
27+
}
28+
unittest {
29+
DumbMatcher!BitType matcher = DumbMatcher(["red", "green"]);
30+
assert(matcher.match("blue") == 0b00);
31+
assert(matcher.match("red") == 0b01);
32+
assert(matcher.match("green") == 0b10);
33+
assert(matcher.match("red green") == 0b11);
34+
assert(matcher.match("blue green") == 0b10);
35+
Form form = { Op.ATOM, bitshift: 0};
36+
assert(eval_form(matcher.match("red"), Form(Op.AND, [form])));
37+
}
38+
unittest {
39+
DumbMatcher!BitType matcher = DumbMatcher(["[[PRIME Theory]]", "[[PRIME: Motives]]"]);
40+
assert(matcher.match("- In every moment we [act]([[PRIME: Responses]]) in pursuit of what we most [want or need]([[PRIME: Motives]]) at that moment. Something can only exert [[behavioral influence]] if it is [[salient]] at the moment") == 0b10);
41+
}
42+
}
43+
struct RegexMatcher;
44+
struct TrieMatcher;
45+
46+
alias BitType = uint;
47+
48+
/++Roam query.
49+
+ It handles a stream of START and END events.
50+
+ START means a indented block or line started
51+
+ END means a indented block or line ended
52+
+
53+
+ It computes a bitfield for each line.
54+
+ Each bit in the bitfield corresponds to a word in the query, and represents
55+
+ whether that bit was present in this line or one of its parents.
56+
+/
57+
struct QueryHandler {
58+
bool matching = false;
59+
string[] parent_lines; // Bookkeeping data structure. Holds parent lines as strings, so we can later print them out.
60+
//string[] to_print;
61+
BitType[] bit_stack = [0];
62+
DumbMatcher!BitType matcher;
63+
Form expression;
64+
this(string[] terms, Form form) { // Construct a QueryHandler struct
65+
debug writeln("Terms", terms);
66+
assert(terms.length < BitType.sizeof * 8);
67+
matcher = DumbMatcher!BitType(terms);
68+
expression = form;
69+
}
70+
void start(string line) {
71+
BitType own_bits = matcher.match(line);
72+
bit_stack ~= bit_stack[$-1] | own_bits;
73+
debug writeln("Own bitstring", own_bits);
74+
parent_lines ~= line;
75+
if (eval_form(bit_stack[$-1], expression)) {
76+
import std.stdio;
77+
foreach (parent_line; parent_lines)
78+
writeln(parent_line);
79+
// Simple way to avoid printing it twice
80+
parent_lines.length = 0;
81+
}
82+
}
83+
void end() {
84+
debug writeln("stacklen", bit_stack.length);
85+
bit_stack.length--;
86+
if (parent_lines.length > 0)
87+
parent_lines = parent_lines[0..$-1]; // Pop the last item
88+
}
89+
}
90+
unittest {
91+
//QueryHandler!uint handler = QueryHandler!uint(["red", "green"], "");
92+
}

0 commit comments

Comments
 (0)