Skip to content

Commit 3da1b7d

Browse files
committed
[script] Fix issue with partial updates and expression folding
1 parent 88dc983 commit 3da1b7d

9 files changed

Lines changed: 802 additions & 45 deletions

File tree

distr/flecs.c

Lines changed: 97 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50322,6 +50322,7 @@ typedef struct ecs_expr_initializer_t {
5032250322
const ecs_type_info_t *type_info;
5032350323
bool is_collection;
5032450324
bool is_dynamic;
50325+
bool is_partial;
5032550326
} ecs_expr_initializer_t;
5032650327

5032750328
typedef struct ecs_expr_variable_t {
@@ -66830,6 +66831,15 @@ void FlecsScriptMathPerlinImport(
6683066831
case '\n':\
6683166832
case '\0'
6683266833

66834+
static
66835+
void flecs_script_initializer_set_full(
66836+
ecs_expr_node_t *node)
66837+
{
66838+
if (node->kind == EcsExprInitializer) {
66839+
((ecs_expr_initializer_t*)node)->is_partial = false;
66840+
}
66841+
}
66842+
6683366843
/* Parse scope (statements inside {}) */
6683466844
static
6683566845
const char* flecs_script_scope(
@@ -66942,6 +66952,7 @@ const char* flecs_script_with_expr(
6694266952
flecs_script_insert_component(parser, Token(0));
6694366953
component->node.kind = EcsAstWithComponent;
6694466954
component->expr = INITIALIZER;
66955+
flecs_script_initializer_set_full(component->expr);
6694566956
EndOfRule;
6694666957
)
6694766958
)
@@ -66970,10 +66981,11 @@ const char* flecs_script_with_expr(
6697066981
// (Eats, Apples) ( expr )
6697166982
Initializer(')',
6697266983
ecs_script_component_t *component =
66973-
flecs_script_insert_pair_component(parser,
66984+
flecs_script_insert_pair_component(parser,
6697466985
Token(1), Token(3));
6697566986
component->node.kind = EcsAstWithComponent;
6697666987
component->expr = INITIALIZER;
66988+
flecs_script_initializer_set_full(component->expr);
6697766989
EndOfRule;
6697866990
)
6697966991
)
@@ -67038,10 +67050,11 @@ const char* flecs_script_paren_expr(
6703867050
Initializer(')',
6703967051
entity->kind_w_expr = true;
6704067052

67041-
Scope(entity->scope,
67042-
ecs_script_component_t *component =
67053+
Scope(entity->scope,
67054+
ecs_script_component_t *component =
6704367055
flecs_script_insert_component(parser, kind);
6704467056
component->expr = INITIALIZER;
67057+
flecs_script_initializer_set_full(component->expr);
6704567058
)
6704667059

6704767060
Parse(
@@ -67980,10 +67993,11 @@ identifier_paren: {
6798067993
ecs_script_entity_t *entity = flecs_script_insert_entity(
6798167994
parser, NULL);
6798267995

67983-
Scope(entity->scope,
67984-
ecs_script_component_t *comp =
67985-
flecs_script_insert_component(parser, Token(0));
67996+
Scope(entity->scope,
67997+
ecs_script_component_t *comp =
67998+
flecs_script_insert_component(parser, Token(0));
6798667999
comp->expr = INITIALIZER;
68000+
flecs_script_initializer_set_full(comp->expr);
6798768001
)
6798868002

6798968003
EndOfRule;
@@ -67994,10 +68008,11 @@ identifier_paren: {
6799468008
ecs_script_entity_t *entity = flecs_script_insert_entity(
6799568009
parser, NULL);
6799668010

67997-
Scope(entity->scope,
67998-
ecs_script_component_t *comp =
67999-
flecs_script_insert_component(parser, Token(0));
68011+
Scope(entity->scope,
68012+
ecs_script_component_t *comp =
68013+
flecs_script_insert_component(parser, Token(0));
6800068014
comp->expr = INITIALIZER;
68015+
flecs_script_initializer_set_full(comp->expr);
6800168016
)
6800268017

6800368018
return flecs_script_scope(parser, entity->scope, pos);
@@ -71822,25 +71837,44 @@ int flecs_script_eval_component(
7182271837
}
7182371838

7182471839
bool needs_set = ti->hooks.on_replace != NULL;
71825-
ecs_record_t *r = flecs_entities_get(v->world, src);
71826-
ecs_assert(r != NULL, ECS_INTERNAL_ERROR, NULL);
71827-
ecs_table_t *table = r->table;
71828-
71840+
71841+
bool partial = false;
71842+
if (node->expr->kind == EcsExprInitializer) {
71843+
partial = ((ecs_expr_initializer_t*)node->expr)->is_partial;
71844+
}
71845+
71846+
const void *existing = NULL;
71847+
if (partial) {
71848+
existing = ecs_get_id(v->world, src, node->id.eval);
71849+
}
71850+
7182971851
ecs_value_t value = {
71830-
.ptr = needs_set
71831-
? ecs_os_alloca(ti->size)
71832-
: ecs_ensure_id(v->world, src, node->id.eval,
71852+
.ptr = needs_set
71853+
? ecs_os_alloca(ti->size)
71854+
: ecs_ensure_id(v->world, src, node->id.eval,
7183371855
flecs_ito(size_t, ti->size)),
7183471856
.type = ti->component
7183571857
};
7183671858

71837-
/* Assign entire value, including members not set by expression. This
71838-
* prevents uninitialized or unexpected values. */
71839-
if (needs_set || (r->table != table)) {
71859+
/* For full assignments, assign entire value including members not set
71860+
* by expression. This prevents uninitialized or unexpected values. For
71861+
* partial assignments, members not set by the expression keep the
71862+
* existing component value. */
71863+
if (needs_set) {
7184071864
if (!ti->hooks.ctor) {
7184171865
ecs_os_memset(value.ptr, 0, ti->size);
7184271866
} else {
71843-
if (!needs_set && ti->hooks.dtor) {
71867+
flecs_type_info_ctor(value.ptr, 1, ti);
71868+
}
71869+
71870+
if (existing) {
71871+
ecs_value_copy_w_type_info(v->world, ti, value.ptr, existing);
71872+
}
71873+
} else if (!existing) {
71874+
if (!ti->hooks.ctor) {
71875+
ecs_os_memset(value.ptr, 0, ti->size);
71876+
} else {
71877+
if (ti->hooks.dtor) {
7184471878
flecs_type_info_dtor(value.ptr, 1, ti);
7184571879
}
7184671880
flecs_type_info_ctor(value.ptr, 1, ti);
@@ -71972,12 +72006,33 @@ int flecs_script_eval_default_component(
7197272006
return -1;
7197372007
}
7197472008

72009+
bool partial = false;
72010+
if (node->expr->kind == EcsExprInitializer) {
72011+
partial = ((ecs_expr_initializer_t*)node->expr)->is_partial;
72012+
}
72013+
72014+
const void *existing = NULL;
72015+
if (partial) {
72016+
existing = ecs_get_id(v->world, v->entity->eval, default_type);
72017+
}
72018+
7197572019
ecs_value_t value = {
71976-
.ptr = ecs_ensure_id(v->world, v->entity->eval, default_type,
72020+
.ptr = ecs_ensure_id(v->world, v->entity->eval, default_type,
7197772021
flecs_ito(size_t, ti->size)),
7197872022
.type = default_type
7197972023
};
7198072024

72025+
if (!existing) {
72026+
if (!ti->hooks.ctor) {
72027+
ecs_os_memset(value.ptr, 0, ti->size);
72028+
} else {
72029+
if (ti->hooks.dtor) {
72030+
flecs_type_info_dtor(value.ptr, 1, ti);
72031+
}
72032+
flecs_type_info_ctor(value.ptr, 1, ti);
72033+
}
72034+
}
72035+
7198172036
if (flecs_script_eval_expr(v, &node->expr, &value)) {
7198272037
return -1;
7198372038
}
@@ -93044,6 +93099,16 @@ const char* flecs_script_parse_initializer(
9304493099
goto error;
9304593100
}
9304693101

93102+
if (elem->member) {
93103+
node->is_partial = true;
93104+
}
93105+
93106+
if (elem->value && elem->value->kind == EcsExprInitializer &&
93107+
((ecs_expr_initializer_t*)elem->value)->is_partial)
93108+
{
93109+
node->is_partial = true;
93110+
}
93111+
9304793112
{
9304893113
/* Parse next element or end of initializer */
9304993114
LookAhead(
@@ -93053,7 +93118,7 @@ const char* flecs_script_parse_initializer(
9305393118
}
9305493119

9305593120
case ')':
93056-
case '}':
93121+
case '}':
9305793122
/* Return last character of initializer */
9305893123
pos = lookahead - 1;
9305993124

@@ -93108,6 +93173,12 @@ const char* flecs_script_parse_collection_initializer(
9310893173
goto error;
9310993174
}
9311093175

93176+
if (elem->value && elem->value->kind == EcsExprInitializer &&
93177+
((ecs_expr_initializer_t*)elem->value)->is_partial)
93178+
{
93179+
node->is_partial = true;
93180+
}
93181+
9311193182
{
9311293183
/* Parse next element or end of initializer */
9311393184
LookAhead(
@@ -95907,6 +95978,10 @@ int flecs_expr_initializer_visit_fold(
9590795978

9590895979
ecs_expr_initializer_t *node = (ecs_expr_initializer_t*)*node_ptr;
9590995980

95981+
if (node->is_partial) {
95982+
can_fold = false;
95983+
}
95984+
9591095985
if (flecs_expr_initializer_pre_fold(script, node, desc, &can_fold)) {
9591195986
goto error;
9591295987
}

src/addons/script/expr/ast.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ typedef struct ecs_expr_initializer_t {
6464
const ecs_type_info_t *type_info;
6565
bool is_collection;
6666
bool is_dynamic;
67+
bool is_partial;
6768
} ecs_expr_initializer_t;
6869

6970
typedef struct ecs_expr_variable_t {

src/addons/script/expr/parser.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,16 @@ const char* flecs_script_parse_initializer(
198198
goto error;
199199
}
200200

201+
if (elem->member) {
202+
node->is_partial = true;
203+
}
204+
205+
if (elem->value && elem->value->kind == EcsExprInitializer &&
206+
((ecs_expr_initializer_t*)elem->value)->is_partial)
207+
{
208+
node->is_partial = true;
209+
}
210+
201211
{
202212
/* Parse next element or end of initializer */
203213
LookAhead(
@@ -207,7 +217,7 @@ const char* flecs_script_parse_initializer(
207217
}
208218

209219
case ')':
210-
case '}':
220+
case '}':
211221
/* Return last character of initializer */
212222
pos = lookahead - 1;
213223

@@ -262,6 +272,12 @@ const char* flecs_script_parse_collection_initializer(
262272
goto error;
263273
}
264274

275+
if (elem->value && elem->value->kind == EcsExprInitializer &&
276+
((ecs_expr_initializer_t*)elem->value)->is_partial)
277+
{
278+
node->is_partial = true;
279+
}
280+
265281
{
266282
/* Parse next element or end of initializer */
267283
LookAhead(

src/addons/script/expr/visit_fold.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ int flecs_expr_initializer_visit_fold(
349349

350350
ecs_expr_initializer_t *node = (ecs_expr_initializer_t*)*node_ptr;
351351

352+
if (node->is_partial) {
353+
can_fold = false;
354+
}
355+
352356
if (flecs_expr_initializer_pre_fold(script, node, desc, &can_fold)) {
353357
goto error;
354358
}

src/addons/script/parser.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@
1515
case '\n':\
1616
case '\0'
1717

18+
static
19+
void flecs_script_initializer_set_full(
20+
ecs_expr_node_t *node)
21+
{
22+
if (node->kind == EcsExprInitializer) {
23+
((ecs_expr_initializer_t*)node)->is_partial = false;
24+
}
25+
}
26+
1827
/* Parse scope (statements inside {}) */
1928
static
2029
const char* flecs_script_scope(
@@ -127,6 +136,7 @@ const char* flecs_script_with_expr(
127136
flecs_script_insert_component(parser, Token(0));
128137
component->node.kind = EcsAstWithComponent;
129138
component->expr = INITIALIZER;
139+
flecs_script_initializer_set_full(component->expr);
130140
EndOfRule;
131141
)
132142
)
@@ -155,10 +165,11 @@ const char* flecs_script_with_expr(
155165
// (Eats, Apples) ( expr )
156166
Initializer(')',
157167
ecs_script_component_t *component =
158-
flecs_script_insert_pair_component(parser,
168+
flecs_script_insert_pair_component(parser,
159169
Token(1), Token(3));
160170
component->node.kind = EcsAstWithComponent;
161171
component->expr = INITIALIZER;
172+
flecs_script_initializer_set_full(component->expr);
162173
EndOfRule;
163174
)
164175
)
@@ -223,10 +234,11 @@ const char* flecs_script_paren_expr(
223234
Initializer(')',
224235
entity->kind_w_expr = true;
225236

226-
Scope(entity->scope,
227-
ecs_script_component_t *component =
237+
Scope(entity->scope,
238+
ecs_script_component_t *component =
228239
flecs_script_insert_component(parser, kind);
229240
component->expr = INITIALIZER;
241+
flecs_script_initializer_set_full(component->expr);
230242
)
231243

232244
Parse(
@@ -1165,10 +1177,11 @@ identifier_paren: {
11651177
ecs_script_entity_t *entity = flecs_script_insert_entity(
11661178
parser, NULL);
11671179

1168-
Scope(entity->scope,
1169-
ecs_script_component_t *comp =
1170-
flecs_script_insert_component(parser, Token(0));
1180+
Scope(entity->scope,
1181+
ecs_script_component_t *comp =
1182+
flecs_script_insert_component(parser, Token(0));
11711183
comp->expr = INITIALIZER;
1184+
flecs_script_initializer_set_full(comp->expr);
11721185
)
11731186

11741187
EndOfRule;
@@ -1179,10 +1192,11 @@ identifier_paren: {
11791192
ecs_script_entity_t *entity = flecs_script_insert_entity(
11801193
parser, NULL);
11811194

1182-
Scope(entity->scope,
1183-
ecs_script_component_t *comp =
1184-
flecs_script_insert_component(parser, Token(0));
1195+
Scope(entity->scope,
1196+
ecs_script_component_t *comp =
1197+
flecs_script_insert_component(parser, Token(0));
11851198
comp->expr = INITIALIZER;
1199+
flecs_script_initializer_set_full(comp->expr);
11861200
)
11871201

11881202
return flecs_script_scope(parser, entity->scope, pos);

0 commit comments

Comments
 (0)