@@ -35571,8 +35571,9 @@ typedef struct ecs_rule_var_t {
3557135571/* -- Instruction kinds -- */
3557235572typedef enum {
3557335573 EcsRuleAnd, /* And operator: find or match id against variable source */
35574+ EcsRuleAndId, /* And operator for fixed id (no wildcards/variables) */
3557435575 EcsRuleWith, /* Match id against fixed or variable source */
35575- EcsRuleAndAny, /* And operation with support for matching Any src/id */
35576+ EcsRuleAndAny, /* And operator with support for matching Any src/id */
3557635577 EcsRuleTrav, /* Support for transitive/reflexive queries */
3557735578 EcsRuleIdsRight, /* Find ids in use that match (R, *) wildcard */
3557835579 EcsRuleIdsLeft, /* Find ids in use that match (*, T) wildcard */
@@ -35584,6 +35585,7 @@ typedef enum {
3558435585 EcsRuleSetVars, /* Populate it.sources from variables */
3558535586 EcsRuleSetThis, /* Populate This entity variable */
3558635587 EcsRuleSetFixed, /* Set fixed source entity ids */
35588+ EcsRuleSetIds, /* Set fixed (component) ids */
3558735589 EcsRuleContain, /* Test if table contains entity */
3558835590 EcsRulePairEq, /* Test if both elements of pair are the same */
3558935591 EcsRuleSetCond, /* Set conditional value for EcsRuleJmpCondFalse */
@@ -35815,6 +35817,7 @@ void flecs_rule_trav_cache_fini(
3581535817static bool flecs_rule_op_is_test[] = {
3581635818 [EcsRuleAnd] = true,
3581735819 [EcsRuleAndAny] = true,
35820+ [EcsRuleAndId] = true,
3581835821 [EcsRuleWith] = true,
3581935822 [EcsRuleTrav] = true,
3582035823 [EcsRuleContain] = true,
@@ -36799,6 +36802,44 @@ void flecs_rule_insert_pair_eq(
3679936802 flecs_rule_op_insert(&contains, ctx);
3680036803}
3680136804
36805+ static
36806+ bool flecs_rule_term_fixed_id(
36807+ ecs_filter_t *filter,
36808+ ecs_term_t *term)
36809+ {
36810+ /* Transitive/inherited terms have variable ids */
36811+ if (term->flags & (EcsTermTransitive|EcsTermIdInherited)) {
36812+ return false;
36813+ }
36814+
36815+ /* Or terms can match different ids */
36816+ if (term->oper == EcsOr) {
36817+ return false;
36818+ }
36819+ if ((term != filter->terms) && term[-1].oper == EcsOr) {
36820+ return false;
36821+ }
36822+
36823+ /* Wildcards can assume different ids */
36824+ if (ecs_id_is_wildcard(term->id)) {
36825+ return false;
36826+ }
36827+
36828+ /* Any terms can have fixed ids, but they require special handling */
36829+ if (term->flags & (EcsTermMatchAny|EcsTermMatchAnySrc)) {
36830+ return false;
36831+ }
36832+
36833+ /* First terms that are Not or Optional require special handling */
36834+ if (term->oper == EcsNot || term->oper == EcsOptional) {
36835+ if (term == filter->terms) {
36836+ return false;
36837+ }
36838+ }
36839+
36840+ return true;
36841+ }
36842+
3680236843static
3680336844void flecs_rule_compile_term(
3680436845 ecs_world_t *world,
@@ -36824,11 +36865,19 @@ void flecs_rule_compile_term(
3682436865 ecs_assert(ecs_term_id_is_set(&term->second), ECS_INTERNAL_ERROR, NULL);
3682536866 op.kind = EcsRuleTrav;
3682636867 } else {
36827- if (term->flags & EcsTermMatchAny || term->flags & EcsTermMatchAnySrc) {
36868+ if (term->flags & ( EcsTermMatchAny| EcsTermMatchAnySrc) ) {
3682836869 op.kind = EcsRuleAndAny;
3682936870 }
3683036871 }
3683136872
36873+ /* If term has fixed id, insert simpler instruction that skips dealing with
36874+ * wildcard terms and variables */
36875+ if (flecs_rule_term_fixed_id(&rule->filter, term)) {
36876+ if (op.kind == EcsRuleAnd) {
36877+ op.kind = EcsRuleAndId;
36878+ }
36879+ }
36880+
3683236881 /* Save write state at start of term so we can use it to reliably track
3683336882 * variables got written by this term. */
3683436883 ecs_write_flags_t cond_write_state = ctx->cond_written;
@@ -37038,6 +37087,19 @@ void flecs_rule_compile(
3703837087 }
3703937088 }
3704037089
37090+ /* If the rule contains terms with fixed ids (no wildcards, variables),
37091+ * insert instruction that initializes ecs_iter_t::ids. This allows for the
37092+ * insertion of simpler instructions later on. */
37093+ for (i = 0; i < count; i ++) {
37094+ ecs_term_t *term = &terms[i];
37095+ if (flecs_rule_term_fixed_id(filter, term)) {
37096+ ecs_rule_op_t set_ids = {0};
37097+ set_ids.kind = EcsRuleSetIds;
37098+ flecs_rule_op_insert(&set_ids, &ctx);
37099+ break;
37100+ }
37101+ }
37102+
3704137103 /* Compile query terms to instructions */
3704237104 for (i = 0; i < count; i ++) {
3704337105 ecs_term_t *term = &terms[i];
@@ -37164,6 +37226,7 @@ const char* flecs_rule_op_str(
3716437226{
3716537227 switch(kind) {
3716637228 case EcsRuleAnd: return "and ";
37229+ case EcsRuleAndId: return "and_id ";
3716737230 case EcsRuleAndAny: return "andany ";
3716837231 case EcsRuleWith: return "with ";
3716937232 case EcsRuleTrav: return "trav ";
@@ -37177,6 +37240,7 @@ const char* flecs_rule_op_str(
3717737240 case EcsRuleSetVars: return "setvars ";
3717837241 case EcsRuleSetThis: return "setthis ";
3717937242 case EcsRuleSetFixed: return "setfix ";
37243+ case EcsRuleSetIds: return "setids ";
3718037244 case EcsRuleContain: return "contain ";
3718137245 case EcsRulePairEq: return "pair_eq ";
3718237246 case EcsRuleSetCond: return "setcond ";
@@ -38045,6 +38109,7 @@ bool flecs_rule_select_w_id(
3804538109 op_ctx->column = flecs_ito(int16_t, tr->column);
3804638110 op_ctx->remaining = flecs_ito(int16_t, tr->count - 1);
3804738111 table = tr->hdr.table;
38112+ flecs_rule_var_set_table(op, op->src.var, table, 0, 0, ctx);
3804838113 } else {
3804938114 tr = (ecs_table_record_t*)op_ctx->it.cur;
3805038115 ecs_assert(tr != NULL, ECS_INTERNAL_ERROR, NULL);
@@ -38053,8 +38118,6 @@ bool flecs_rule_select_w_id(
3805338118 op_ctx->remaining --;
3805438119 }
3805538120
38056- ecs_var_id_t var_id = op->src.var;
38057- flecs_rule_var_set_table(op, var_id, table, 0, 0, ctx);
3805838121 flecs_rule_set_match(op, table, op_ctx->column, ctx);
3805938122 return true;
3806038123}
@@ -38102,7 +38165,6 @@ bool flecs_rule_with(
3810238165 return false;
3810338166 }
3810438167
38105- op_ctx->idr = idr;
3810638168 op_ctx->column = flecs_ito(int16_t, tr->column);
3810738169 op_ctx->remaining = flecs_ito(int16_t, tr->count);
3810838170 } else {
@@ -38125,13 +38187,103 @@ bool flecs_rule_and(
3812538187 const ecs_rule_run_ctx_t *ctx)
3812638188{
3812738189 uint64_t written = ctx->written[ctx->op_index];
38128- if (written & (1 << op->src.var)) {
38190+ if (written & (1ull << op->src.var)) {
3812938191 return flecs_rule_with(op, redo, ctx);
3813038192 } else {
3813138193 return flecs_rule_select(op, redo, ctx);
3813238194 }
3813338195}
3813438196
38197+ static
38198+ bool flecs_rule_select_id(
38199+ const ecs_rule_op_t *op,
38200+ bool redo,
38201+ const ecs_rule_run_ctx_t *ctx)
38202+ {
38203+ ecs_rule_and_ctx_t *op_ctx = flecs_op_ctx(ctx, and);
38204+ ecs_iter_t *it = ctx->it;
38205+ int8_t field = op->field_index;
38206+ ecs_assert(field != -1, ECS_INTERNAL_ERROR, NULL);
38207+
38208+ if (!redo) {
38209+ ecs_id_t id = it->ids[field];
38210+ ecs_id_record_t *idr = op_ctx->idr;
38211+ if (!idr || idr->id != id) {
38212+ idr = op_ctx->idr = flecs_id_record_get(ctx->world, id);
38213+ if (!idr) {
38214+ return false;
38215+ }
38216+ }
38217+
38218+ if (!flecs_table_cache_iter(&idr->cache, &op_ctx->it)) {
38219+ return false;
38220+ }
38221+ }
38222+
38223+ const ecs_table_record_t *tr = flecs_table_cache_next(
38224+ &op_ctx->it, ecs_table_record_t);
38225+ if (!tr) {
38226+ return false;
38227+ }
38228+
38229+ ecs_table_t *table = tr->hdr.table;
38230+ flecs_rule_var_set_table(op, op->src.var, table, 0, 0, ctx);
38231+ flecs_rule_it_set_column(it, field, tr->column);
38232+ return true;
38233+ }
38234+
38235+ static
38236+ bool flecs_rule_with_id(
38237+ const ecs_rule_op_t *op,
38238+ bool redo,
38239+ const ecs_rule_run_ctx_t *ctx)
38240+ {
38241+ if (redo) {
38242+ return false;
38243+ }
38244+
38245+ ecs_rule_and_ctx_t *op_ctx = flecs_op_ctx(ctx, and);
38246+ ecs_iter_t *it = ctx->it;
38247+ int8_t field = op->field_index;
38248+ ecs_assert(field != -1, ECS_INTERNAL_ERROR, NULL);
38249+
38250+ ecs_table_t *table = flecs_rule_get_table(op, &op->src, EcsRuleSrc, ctx);
38251+ if (!table) {
38252+ return false;
38253+ }
38254+
38255+ ecs_id_t id = it->ids[field];
38256+ ecs_id_record_t *idr = op_ctx->idr;
38257+ if (!idr || idr->id != id) {
38258+ idr = op_ctx->idr = flecs_id_record_get(ctx->world, id);
38259+ if (!idr) {
38260+ return false;
38261+ }
38262+ }
38263+
38264+ const ecs_table_record_t *tr = flecs_id_record_get_table(idr, table);
38265+ if (!tr) {
38266+ return false;
38267+ }
38268+
38269+ flecs_rule_it_set_column(it, field, tr->column);
38270+ return true;
38271+ }
38272+
38273+ static
38274+ bool flecs_rule_and_id(
38275+ const ecs_rule_op_t *op,
38276+ bool redo,
38277+ const ecs_rule_run_ctx_t *ctx)
38278+ {
38279+ uint64_t written = ctx->written[ctx->op_index];
38280+ if (written & (1 << op->src.var)) {
38281+ return flecs_rule_with_id(op, redo, ctx);
38282+ } else {
38283+ return flecs_rule_select_id(op, redo, ctx);
38284+ }
38285+ }
38286+
3813538287static
3813638288bool flecs_rule_and_any(
3813738289 const ecs_rule_op_t *op,
@@ -38768,6 +38920,30 @@ bool flecs_rule_setfixed(
3876838920 return true;
3876938921}
3877038922
38923+ static
38924+ bool flecs_rule_setids(
38925+ const ecs_rule_op_t *op,
38926+ bool redo,
38927+ ecs_rule_run_ctx_t *ctx)
38928+ {
38929+ (void)op;
38930+ const ecs_rule_t *rule = ctx->rule;
38931+ const ecs_filter_t *filter = &rule->filter;
38932+ ecs_iter_t *it = ctx->it;
38933+
38934+ if (redo) {
38935+ return false;
38936+ }
38937+
38938+ int32_t i;
38939+ for (i = 0; i < filter->term_count; i ++) {
38940+ ecs_term_t *term = &filter->terms[i];
38941+ it->ids[term->field_index] = term->id;
38942+ }
38943+
38944+ return true;
38945+ }
38946+
3877138947/* Check if entity is stored in table */
3877238948static
3877338949bool flecs_rule_contain(
@@ -38875,6 +39051,7 @@ bool flecs_rule_run(
3887539051{
3887639052 switch(op->kind) {
3887739053 case EcsRuleAnd: return flecs_rule_and(op, redo, ctx);
39054+ case EcsRuleAndId: return flecs_rule_and_id(op, redo, ctx);
3887839055 case EcsRuleAndAny: return flecs_rule_and_any(op, redo, ctx);
3887939056 case EcsRuleWith: return flecs_rule_with(op, redo, ctx);
3888039057 case EcsRuleTrav: return flecs_rule_trav(op, redo, ctx);
@@ -38888,6 +39065,7 @@ bool flecs_rule_run(
3888839065 case EcsRuleSetVars: return flecs_rule_setvars(op, redo, ctx);
3888939066 case EcsRuleSetThis: return flecs_rule_setthis(op, redo, ctx);
3889039067 case EcsRuleSetFixed: return flecs_rule_setfixed(op, redo, ctx);
39068+ case EcsRuleSetIds: return flecs_rule_setids(op, redo, ctx);
3889139069 case EcsRuleContain: return flecs_rule_contain(op, redo, ctx);
3889239070 case EcsRulePairEq: return flecs_rule_pair_eq(op, redo, ctx);
3889339071 case EcsRuleJmpCondFalse: return flecs_rule_jmp_if_not(op, redo, ctx);
0 commit comments