Skip to content

Commit 7cec61b

Browse files
committed
Fix issue with evaluating R(_, _) and _(_, T) queries
1 parent 17681dc commit 7cec61b

File tree

9 files changed

+261
-11
lines changed

9 files changed

+261
-11
lines changed

flecs.c

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60744,6 +60744,7 @@ typedef enum {
6074460744
EcsRuleSelfUpId, /* Self|up traversal for fixed id (like AndId) */
6074560745
EcsRuleWith, /* Match id against fixed or variable source */
6074660746
EcsRuleTrav, /* Support for transitive/reflexive queries */
60747+
EcsRuleIds, /* Test for existence of ids matching wildcard */
6074760748
EcsRuleIdsRight, /* Find ids in use that match (R, *) wildcard */
6074860749
EcsRuleIdsLeft, /* Find ids in use that match (*, T) wildcard */
6074960750
EcsRuleEach, /* Iterate entities in table, populate entity variable */
@@ -61157,6 +61158,7 @@ const char* flecs_rule_op_str(
6115761158
case EcsRuleSelfUpId: return "selfupid";
6115861159
case EcsRuleWith: return "with ";
6115961160
case EcsRuleTrav: return "trav ";
61161+
case EcsRuleIds: return "ids ";
6116061162
case EcsRuleIdsRight: return "idsr ";
6116161163
case EcsRuleIdsLeft: return "idsl ";
6116261164
case EcsRuleEach: return "each ";
@@ -63114,10 +63116,18 @@ int flecs_rule_compile_term(
6311463116
if (!first_written || !second_written) {
6311563117
if (!first_written) {
6311663118
/* If first is unknown, traverse left: <- (*, t) */
63117-
op.kind = EcsRuleIdsLeft;
63119+
if (term->first.id == EcsAny) {
63120+
op.kind = EcsRuleIds;
63121+
} else {
63122+
op.kind = EcsRuleIdsLeft;
63123+
}
6311863124
} else {
6311963125
/* If second is wildcard, traverse right: (r, *) -> */
63120-
op.kind = EcsRuleIdsRight;
63126+
if (term->second.id == EcsAny) {
63127+
op.kind = EcsRuleIds;
63128+
} else {
63129+
op.kind = EcsRuleIdsRight;
63130+
}
6312163131
}
6312263132
op.src.entity = 0;
6312363133
op.flags &= (ecs_flags8_t)~(EcsRuleIsVar << EcsRuleSrc); /* ids has no src */
@@ -65041,6 +65051,48 @@ bool flecs_rule_trav(
6504165051
}
6504265052
}
6504365053

65054+
static
65055+
bool flecs_rule_ids(
65056+
const ecs_rule_op_t *op,
65057+
bool redo,
65058+
const ecs_rule_run_ctx_t *ctx)
65059+
{
65060+
if (redo) {
65061+
return false;
65062+
}
65063+
65064+
ecs_rule_ids_ctx_t *op_ctx = flecs_op_ctx(ctx, ids);
65065+
ecs_id_record_t *cur;
65066+
65067+
{
65068+
ecs_id_t id = flecs_rule_op_get_id(op, ctx);
65069+
if (!ecs_id_is_wildcard(id)) {
65070+
/* If id is not a wildcard, we can directly return it. This can
65071+
* happen if a variable was constrained by an iterator. */
65072+
op_ctx->cur = NULL;
65073+
flecs_rule_set_vars(op, id, ctx);
65074+
return true;
65075+
}
65076+
65077+
cur = flecs_id_record_get(ctx->world, id);
65078+
if (!cur) {
65079+
return false;
65080+
}
65081+
}
65082+
65083+
flecs_rule_set_vars(op, cur->id, ctx);
65084+
65085+
if (op->field_index != -1) {
65086+
ecs_iter_t *it = ctx->it;
65087+
ecs_id_t id = flecs_rule_op_get_id_w_written(op, op->written, ctx);
65088+
it->ids[op->field_index] = id;
65089+
it->sources[op->field_index] = EcsWildcard;
65090+
it->columns[op->field_index] = -1; /* Mark field as set */
65091+
}
65092+
65093+
return true;
65094+
}
65095+
6504465096
static
6504565097
bool flecs_rule_idsright(
6504665098
const ecs_rule_op_t *op,
@@ -65084,6 +65136,8 @@ bool flecs_rule_idsright(
6508465136
ecs_iter_t *it = ctx->it;
6508565137
ecs_id_t id = flecs_rule_op_get_id_w_written(op, op->written, ctx);
6508665138
it->ids[op->field_index] = id;
65139+
it->sources[op->field_index] = EcsWildcard;
65140+
it->columns[op->field_index] = -1; /* Mark field as set */
6508765141
}
6508865142

6508965143
return true;
@@ -65132,6 +65186,8 @@ bool flecs_rule_idsleft(
6513265186
ecs_iter_t *it = ctx->it;
6513365187
ecs_id_t id = flecs_rule_op_get_id_w_written(op, op->written, ctx);
6513465188
it->ids[op->field_index] = id;
65189+
it->sources[op->field_index] = EcsWildcard;
65190+
it->columns[op->field_index] = -1; /* Mark field as set */
6513565191
}
6513665192

6513765193
return true;
@@ -66111,6 +66167,7 @@ bool flecs_rule_dispatch(
6611166167
case EcsRuleSelfUpId: return flecs_rule_self_up_id(op, redo, ctx);
6611266168
case EcsRuleWith: return flecs_rule_with(op, redo, ctx);
6611366169
case EcsRuleTrav: return flecs_rule_trav(op, redo, ctx);
66170+
case EcsRuleIds: return flecs_rule_ids(op, redo, ctx);
6611466171
case EcsRuleIdsRight: return flecs_rule_idsright(op, redo, ctx);
6611566172
case EcsRuleIdsLeft: return flecs_rule_idsleft(op, redo, ctx);
6611666173
case EcsRuleEach: return flecs_rule_each(op, redo, ctx);

src/addons/rules/api.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const char* flecs_rule_op_str(
3535
case EcsRuleSelfUpId: return "selfupid";
3636
case EcsRuleWith: return "with ";
3737
case EcsRuleTrav: return "trav ";
38+
case EcsRuleIds: return "ids ";
3839
case EcsRuleIdsRight: return "idsr ";
3940
case EcsRuleIdsLeft: return "idsl ";
4041
case EcsRuleEach: return "each ";

src/addons/rules/compile.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,10 +1571,18 @@ int flecs_rule_compile_term(
15711571
if (!first_written || !second_written) {
15721572
if (!first_written) {
15731573
/* If first is unknown, traverse left: <- (*, t) */
1574-
op.kind = EcsRuleIdsLeft;
1574+
if (term->first.id == EcsAny) {
1575+
op.kind = EcsRuleIds;
1576+
} else {
1577+
op.kind = EcsRuleIdsLeft;
1578+
}
15751579
} else {
15761580
/* If second is wildcard, traverse right: (r, *) -> */
1577-
op.kind = EcsRuleIdsRight;
1581+
if (term->second.id == EcsAny) {
1582+
op.kind = EcsRuleIds;
1583+
} else {
1584+
op.kind = EcsRuleIdsRight;
1585+
}
15781586
}
15791587
op.src.entity = 0;
15801588
op.flags &= (ecs_flags8_t)~(EcsRuleIsVar << EcsRuleSrc); /* ids has no src */

src/addons/rules/engine.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,48 @@ bool flecs_rule_trav(
13081308
}
13091309
}
13101310

1311+
static
1312+
bool flecs_rule_ids(
1313+
const ecs_rule_op_t *op,
1314+
bool redo,
1315+
const ecs_rule_run_ctx_t *ctx)
1316+
{
1317+
if (redo) {
1318+
return false;
1319+
}
1320+
1321+
ecs_rule_ids_ctx_t *op_ctx = flecs_op_ctx(ctx, ids);
1322+
ecs_id_record_t *cur;
1323+
1324+
{
1325+
ecs_id_t id = flecs_rule_op_get_id(op, ctx);
1326+
if (!ecs_id_is_wildcard(id)) {
1327+
/* If id is not a wildcard, we can directly return it. This can
1328+
* happen if a variable was constrained by an iterator. */
1329+
op_ctx->cur = NULL;
1330+
flecs_rule_set_vars(op, id, ctx);
1331+
return true;
1332+
}
1333+
1334+
cur = flecs_id_record_get(ctx->world, id);
1335+
if (!cur) {
1336+
return false;
1337+
}
1338+
}
1339+
1340+
flecs_rule_set_vars(op, cur->id, ctx);
1341+
1342+
if (op->field_index != -1) {
1343+
ecs_iter_t *it = ctx->it;
1344+
ecs_id_t id = flecs_rule_op_get_id_w_written(op, op->written, ctx);
1345+
it->ids[op->field_index] = id;
1346+
it->sources[op->field_index] = EcsWildcard;
1347+
it->columns[op->field_index] = -1; /* Mark field as set */
1348+
}
1349+
1350+
return true;
1351+
}
1352+
13111353
static
13121354
bool flecs_rule_idsright(
13131355
const ecs_rule_op_t *op,
@@ -1351,6 +1393,8 @@ bool flecs_rule_idsright(
13511393
ecs_iter_t *it = ctx->it;
13521394
ecs_id_t id = flecs_rule_op_get_id_w_written(op, op->written, ctx);
13531395
it->ids[op->field_index] = id;
1396+
it->sources[op->field_index] = EcsWildcard;
1397+
it->columns[op->field_index] = -1; /* Mark field as set */
13541398
}
13551399

13561400
return true;
@@ -1399,6 +1443,8 @@ bool flecs_rule_idsleft(
13991443
ecs_iter_t *it = ctx->it;
14001444
ecs_id_t id = flecs_rule_op_get_id_w_written(op, op->written, ctx);
14011445
it->ids[op->field_index] = id;
1446+
it->sources[op->field_index] = EcsWildcard;
1447+
it->columns[op->field_index] = -1; /* Mark field as set */
14021448
}
14031449

14041450
return true;
@@ -2378,6 +2424,7 @@ bool flecs_rule_dispatch(
23782424
case EcsRuleSelfUpId: return flecs_rule_self_up_id(op, redo, ctx);
23792425
case EcsRuleWith: return flecs_rule_with(op, redo, ctx);
23802426
case EcsRuleTrav: return flecs_rule_trav(op, redo, ctx);
2427+
case EcsRuleIds: return flecs_rule_ids(op, redo, ctx);
23812428
case EcsRuleIdsRight: return flecs_rule_idsright(op, redo, ctx);
23822429
case EcsRuleIdsLeft: return flecs_rule_idsleft(op, redo, ctx);
23832430
case EcsRuleEach: return flecs_rule_each(op, redo, ctx);

src/addons/rules/rules.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ typedef enum {
5050
EcsRuleSelfUpId, /* Self|up traversal for fixed id (like AndId) */
5151
EcsRuleWith, /* Match id against fixed or variable source */
5252
EcsRuleTrav, /* Support for transitive/reflexive queries */
53+
EcsRuleIds, /* Test for existence of ids matching wildcard */
5354
EcsRuleIdsRight, /* Find ids in use that match (R, *) wildcard */
5455
EcsRuleIdsLeft, /* Find ids in use that match (*, T) wildcard */
5556
EcsRuleEach, /* Iterate entities in table, populate entity variable */

test/addons/project.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,8 @@
751751
"1_any_src_w_pair_rel_var",
752752
"1_any_src_w_pair_tgt_this",
753753
"1_any_src_w_pair_rel_this",
754+
"1_any_src_any_tgt_w_rel_fixed",
755+
"1_any_src_any_rel_w_tgt_fixed",
754756
"not_any",
755757
"rule_w_iter_next",
756758
"empty_rule",

0 commit comments

Comments
 (0)