compiled_query.js
· 3.7 KiB · JavaScript
Orginalformat
Playground
/*
|
lightning struck $x $y
, $something is at $x $y?
, $something has inventory $inventory?
, $inventory has item $item?
, $item is $class?
, $class is conductive?
|
$something is struck by lightning
*/
plans._lightning_struck_x_y = function (match, patterns) {
for(let [_x, _y] of patterns._lightning_struck_x_y) {
match.state._lightning_struck_x_y = true;
match.vars._x = _x;
match.vars._y = _y;
if (
match.state._something_is_at_x_y || plans._something_is_at_x_y(match, patterns)
) {
return true;
} else { return false; }
}
}
plans._something_is_at_x_y = function (match, patterns) {
for(let [_something, _x, _y] of patterns._something_is_at_x_y) {
match.state._something_is_at_x_y = true;
match.vars._something = _something;
match.vars._x = _x;
match.vars._y = _y;
if (
match.state._something_has_inventory_inventory || plans._something_has_inventory_inventory(match, p
atterns) &&
match.state._lightning_struck_x_y || plans._lightning_struck_x_y(match, patterns)
) {
return true;
} else { return false; }
}
}
plans._something_has_inventory_inventory = function (match, patterns) {
for(let [_something, _inventory] of patterns._something_has_inventory_inventory) {
match.state._something_has_inventory_inventory = true;
match.vars._something = _something;
match.vars._inventory = _inventory;
if (
match.state._something_is_at_x_y || plans._something_is_at_x_y(match, patterns) &&
match.state._inventory_has_item_item || plans._inventory_has_item_item(match, patterns)
) {
return true;
} else { return false; }
}
}
plans._inventory_has_item_item = function (match, patterns) {
for(let [_inventory, _item] of patterns._inventory_has_item_item) {
match.state._inventory_has_item_item = true;
match.vars._inventory = _inventory;
match.vars._item = _item;
if (
match.state._something_has_inventory_inventory || plans._something_has_inventory_inventory(match, p
atterns) &&
match.state._item_is_class || plans._item_is_class(match, patterns)
) {
return true;
} else { return false; }
}
}
plans._item_is_class = function (match, patterns) {
for(let [_item, _class] of patterns._item_is_class) {
match.state._item_is_class = true;
match.vars._item = _item;
match.vars._class = _class;
if (
match.state._inventory_has_item_item || plans._inventory_has_item_item(match, patterns) &&
match.state._class_is_conductive || plans._class_is_conductive(match, patterns)
) {
return true;
} else { return false; }
}
}
plans._class_is_conductive = function (match, patterns) {
for(let [_class] of patterns._class_is_conductive) {
match.state._class_is_conductive = true;
match.vars._class = _class;
if (
match.state._item_is_class || plans._item_is_class(match, patterns)
) {
return true;
} else { return false; }
}
}
1 | /* |
2 | | |
3 | lightning struck $x $y |
4 | , $something is at $x $y? |
5 | , $something has inventory $inventory? |
6 | , $inventory has item $item? |
7 | , $item is $class? |
8 | , $class is conductive? |
9 | | |
10 | $something is struck by lightning |
11 | |
12 | */ |
13 | |
14 | plans._lightning_struck_x_y = function (match, patterns) { |
15 | for(let [_x, _y] of patterns._lightning_struck_x_y) { |
16 | match.state._lightning_struck_x_y = true; |
17 | match.vars._x = _x; |
18 | match.vars._y = _y; |
19 | if ( |
20 | match.state._something_is_at_x_y || plans._something_is_at_x_y(match, patterns) |
21 | |
22 | ) { |
23 | return true; |
24 | } else { return false; } |
25 | } |
26 | } |
27 | |
28 | |
29 | |
30 | |
31 | plans._something_is_at_x_y = function (match, patterns) { |
32 | for(let [_something, _x, _y] of patterns._something_is_at_x_y) { |
33 | match.state._something_is_at_x_y = true; |
34 | match.vars._something = _something; |
35 | match.vars._x = _x; |
36 | match.vars._y = _y; |
37 | if ( |
38 | match.state._something_has_inventory_inventory || plans._something_has_inventory_inventory(match, p |
39 | atterns) && |
40 | match.state._lightning_struck_x_y || plans._lightning_struck_x_y(match, patterns) |
41 | |
42 | ) { |
43 | return true; |
44 | } else { return false; } |
45 | } |
46 | } |
47 | |
48 | |
49 | |
50 | |
51 | plans._something_has_inventory_inventory = function (match, patterns) { |
52 | for(let [_something, _inventory] of patterns._something_has_inventory_inventory) { |
53 | match.state._something_has_inventory_inventory = true; |
54 | match.vars._something = _something; |
55 | match.vars._inventory = _inventory; |
56 | if ( |
57 | match.state._something_is_at_x_y || plans._something_is_at_x_y(match, patterns) && |
58 | match.state._inventory_has_item_item || plans._inventory_has_item_item(match, patterns) |
59 | |
60 | ) { |
61 | return true; |
62 | } else { return false; } |
63 | } |
64 | } |
65 | |
66 | |
67 | |
68 | |
69 | plans._inventory_has_item_item = function (match, patterns) { |
70 | for(let [_inventory, _item] of patterns._inventory_has_item_item) { |
71 | match.state._inventory_has_item_item = true; |
72 | match.vars._inventory = _inventory; |
73 | match.vars._item = _item; |
74 | if ( |
75 | match.state._something_has_inventory_inventory || plans._something_has_inventory_inventory(match, p |
76 | atterns) && |
77 | match.state._item_is_class || plans._item_is_class(match, patterns) |
78 | |
79 | ) { |
80 | return true; |
81 | } else { return false; } |
82 | } |
83 | } |
84 | |
85 | |
86 | |
87 | |
88 | plans._item_is_class = function (match, patterns) { |
89 | for(let [_item, _class] of patterns._item_is_class) { |
90 | match.state._item_is_class = true; |
91 | match.vars._item = _item; |
92 | match.vars._class = _class; |
93 | if ( |
94 | match.state._inventory_has_item_item || plans._inventory_has_item_item(match, patterns) && |
95 | match.state._class_is_conductive || plans._class_is_conductive(match, patterns) |
96 | |
97 | ) { |
98 | return true; |
99 | } else { return false; } |
100 | } |
101 | } |
102 | |
103 | |
104 | |
105 | |
106 | plans._class_is_conductive = function (match, patterns) { |
107 | for(let [_class] of patterns._class_is_conductive) { |
108 | match.state._class_is_conductive = true; |
109 | match.vars._class = _class; |
110 | if ( |
111 | match.state._item_is_class || plans._item_is_class(match, patterns) |
112 | |
113 | ) { |
114 | return true; |
115 | } else { return false; } |
116 | } |
117 | } |
118 | |
119 |
query_compiler.js
· 3.6 KiB · JavaScript
Orginalformat
Playground
function compileRule(ruleTokens, predicates) {
// TODO: compile condiitions into predicates (if they don't match an existing predicate)
// and check predicates for non-standard cost models
// (port with custom costs, constant counters, etc)
let rule = {
predicateIds: [],
predicates: [],
queryPlan: null,
predicateNames: new Map(),
consequenceFn: null,
usedVars: new Set(),
};
for (let c of ruleTokens.condition) {
let { patt: predKey, vars: pattVars } = generalizePattern(c);
pattVars.forEach((pv) => rule.usedVars.add(pv));
if (predicates.lookup(predKey)) {
// rule.predicateNames.set(predKey, n);
rule.predicateIds.push(predicates.indexOf(predKey));
} else {
console.log("NEW");
let { name: n, code: predFn } = makeBasicPatternPredicate(c);
rule.predicateNames.set(predKey, n);
predicates.store(predKey, { code: predFn, vars: pattVars });
rule.predicateIds.push(predicates.indexOf(predKey));
}
rule.predicates.push({
idx: predicates.indexOf(predKey),
name: rule.predicateNames.get(predKey),
pred: predicates.lookup(predKey),
varsForPred: pattVars,
})
}
console.log(["XXX", rule.predicateNames]);
let hyperEdges = new EnsureMap();
for (let predicate of rule.predicates) {
for (let v of predicate.varsForPred) {
hyperEdges.ensureGet(v, new Set()).add(predicate);
}
}
// console.log(hyperEdges);
let matchObjParts = ["let match = {\n"];
let plan_fns = [];
for (let predicate of rule.predicates) {
matchObjParts.push(predicate.name, ": false,\n");
let plan_fn_parts= ["plans.", slug(predicate.name) ," = function ", "(match, patterns) {\n"];
plan_fn_parts.push("\tfor(let ");;
if (predicate.varsForPred.length > 0) {
plan_fn_parts.push("[");
for (let v of predicate.varsForPred) {
plan_fn_parts.push(slug(v), ", ");
}
plan_fn_parts.pop();
plan_fn_parts.push("] ");
} else {
plan_fn_parts.push("_ ");
}
plan_fn_parts.push("of patterns.", slug(predicate.name), ") {\n");
plan_fn_parts.push("\t\tmatch.state.", slug(predicate.name), " = true;\n");
for (let v of predicate.varsForPred) {
plan_fn_parts.push("\t\tmatch.vars.", slug(v), " = ", slug(v), ";\n");
}
let seenPredicates = new Set();
plan_fn_parts.push("\t\tif (\n");
let shouldPop = false;
for (let v of predicate.varsForPred) {
for (let otherPred of hyperEdges.get(v)) {
// console.log({ a: otherPred.idx, b: predicate.idx });
if (otherPred.idx !== predicate.idx && !seenPredicates.has(otherPred.idx)) {
shouldPop = true;
seenPredicates.add(otherPred.idx);
// TODO thing
plan_fn_parts.push(
"\t\t\tmatch.state.", slug(otherPred.name),
" || plans.", slug(otherPred.name), "(match, patterns)", " && \n" );
}
}
// console.log("---");
}
if (shouldPop) {
plan_fn_parts.pop();
plan_fn_parts.push("\n");
}
plan_fn_parts.push("\n\t\t) {\n\t\t\t return true; \n\t\t} else { return false; }\n");
plan_fn_parts.push("\t}\n}\n\n\n");
plan_fns.push(plan_fn_parts.join(""));
}
rule.queryPlan = plan_fns;
return rule;
}
1 | function compileRule(ruleTokens, predicates) { |
2 | // TODO: compile condiitions into predicates (if they don't match an existing predicate) |
3 | // and check predicates for non-standard cost models |
4 | // (port with custom costs, constant counters, etc) |
5 | let rule = { |
6 | predicateIds: [], |
7 | predicates: [], |
8 | queryPlan: null, |
9 | predicateNames: new Map(), |
10 | consequenceFn: null, |
11 | usedVars: new Set(), |
12 | }; |
13 | |
14 | for (let c of ruleTokens.condition) { |
15 | let { patt: predKey, vars: pattVars } = generalizePattern(c); |
16 | pattVars.forEach((pv) => rule.usedVars.add(pv)); |
17 | |
18 | |
19 | if (predicates.lookup(predKey)) { |
20 | // rule.predicateNames.set(predKey, n); |
21 | rule.predicateIds.push(predicates.indexOf(predKey)); |
22 | } else { |
23 | console.log("NEW"); |
24 | let { name: n, code: predFn } = makeBasicPatternPredicate(c); |
25 | rule.predicateNames.set(predKey, n); |
26 | predicates.store(predKey, { code: predFn, vars: pattVars }); |
27 | rule.predicateIds.push(predicates.indexOf(predKey)); |
28 | } |
29 | rule.predicates.push({ |
30 | idx: predicates.indexOf(predKey), |
31 | name: rule.predicateNames.get(predKey), |
32 | pred: predicates.lookup(predKey), |
33 | varsForPred: pattVars, |
34 | }) |
35 | } |
36 | console.log(["XXX", rule.predicateNames]); |
37 | |
38 | let hyperEdges = new EnsureMap(); |
39 | |
40 | for (let predicate of rule.predicates) { |
41 | for (let v of predicate.varsForPred) { |
42 | hyperEdges.ensureGet(v, new Set()).add(predicate); |
43 | } |
44 | } |
45 | |
46 | // console.log(hyperEdges); |
47 | |
48 | let matchObjParts = ["let match = {\n"]; |
49 | let plan_fns = []; |
50 | for (let predicate of rule.predicates) { |
51 | matchObjParts.push(predicate.name, ": false,\n"); |
52 | |
53 | let plan_fn_parts= ["plans.", slug(predicate.name) ," = function ", "(match, patterns) {\n"]; |
54 | |
55 | plan_fn_parts.push("\tfor(let ");; |
56 | if (predicate.varsForPred.length > 0) { |
57 | plan_fn_parts.push("["); |
58 | for (let v of predicate.varsForPred) { |
59 | plan_fn_parts.push(slug(v), ", "); |
60 | } |
61 | plan_fn_parts.pop(); |
62 | plan_fn_parts.push("] "); |
63 | } else { |
64 | plan_fn_parts.push("_ "); |
65 | } |
66 | plan_fn_parts.push("of patterns.", slug(predicate.name), ") {\n"); |
67 | plan_fn_parts.push("\t\tmatch.state.", slug(predicate.name), " = true;\n"); |
68 | |
69 | for (let v of predicate.varsForPred) { |
70 | plan_fn_parts.push("\t\tmatch.vars.", slug(v), " = ", slug(v), ";\n"); |
71 | } |
72 | |
73 | let seenPredicates = new Set(); |
74 | plan_fn_parts.push("\t\tif (\n"); |
75 | let shouldPop = false; |
76 | for (let v of predicate.varsForPred) { |
77 | for (let otherPred of hyperEdges.get(v)) { |
78 | // console.log({ a: otherPred.idx, b: predicate.idx }); |
79 | if (otherPred.idx !== predicate.idx && !seenPredicates.has(otherPred.idx)) { |
80 | shouldPop = true; |
81 | seenPredicates.add(otherPred.idx); |
82 | // TODO thing |
83 | plan_fn_parts.push( |
84 | "\t\t\tmatch.state.", slug(otherPred.name), |
85 | " || plans.", slug(otherPred.name), "(match, patterns)", " && \n" ); |
86 | } |
87 | } |
88 | // console.log("---"); |
89 | } |
90 | if (shouldPop) { |
91 | plan_fn_parts.pop(); |
92 | plan_fn_parts.push("\n"); |
93 | } |
94 | plan_fn_parts.push("\n\t\t) {\n\t\t\t return true; \n\t\t} else { return false; }\n"); |
95 | plan_fn_parts.push("\t}\n}\n\n\n"); |
96 | |
97 | plan_fns.push(plan_fn_parts.join("")); |
98 | } |
99 | rule.queryPlan = plan_fns; |
100 | |
101 | return rule; |
102 | } |
103 |