Skip to content

Commit

Permalink
Add tests for assigning match expressions to components
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderMertens committed Jan 3, 2025
1 parent 12d7c0f commit 9254323
Show file tree
Hide file tree
Showing 5 changed files with 299 additions and 22 deletions.
47 changes: 37 additions & 10 deletions distr/flecs.c
Original file line number Diff line number Diff line change
Expand Up @@ -56942,7 +56942,8 @@ for_stmt: {
Parse_1(EcsTokRange, {
Expr(0, {
ecs_expr_node_t *to = EXPR;
ecs_script_for_range_t *stmt = flecs_script_insert_for_range(parser);
ecs_script_for_range_t *stmt =
flecs_script_insert_for_range(parser);
stmt->loop_var = Token(1);
stmt->from = from;
stmt->to = to;
Expand Down Expand Up @@ -56982,16 +56983,29 @@ pair: {

// (Eats, Apples):
case ':': {
// (Eats, Apples): {
Parse_1('{',
// (Eats, Apples): { expr }
Initializer('}',
// Use lookahead so that expression parser starts at "match"
LookAhead_1(EcsTokKeywordMatch, {
// (Eats, Apples): match expr
Expr('\n', {
ecs_script_component_t *comp =
flecs_script_insert_pair_component(
parser, Token(1), Token(3));
comp->expr = INITIALIZER;
EndOfRule;
)
comp->expr = EXPR;
EndOfRule;
})
})

// (Eats, Apples): {
Parse_1('{', {
// (Eats, Apples): { expr }
Initializer('}',
ecs_script_component_t *comp =
flecs_script_insert_pair_component(
parser, Token(1), Token(3));
comp->expr = INITIALIZER;
EndOfRule;
)
}
)
}

Expand Down Expand Up @@ -57061,8 +57075,9 @@ identifier_flag: {
Parse_1('{',
// auto_override | Position: {expr}
Expr('}', {
ecs_script_component_t *comp = flecs_script_insert_component(
parser, Token(2));
ecs_script_component_t *comp =
flecs_script_insert_component(
parser, Token(2));
comp->expr = EXPR;
EndOfRule;
})
Expand Down Expand Up @@ -57133,6 +57148,18 @@ identifier_assign: {
LookAhead_2(EcsTokIdentifier, ':',
pos = lookahead;

// Use lookahead so that expression parser starts at "match"
LookAhead_1(EcsTokKeywordMatch, {
// (Eats, Apples): match expr
Expr('\n', {
ecs_script_component_t *comp =
flecs_script_insert_pair_component(
parser, Token(1), Token(3));
comp->expr = EXPR;
EndOfRule;
})
})

// x = Position: {
Parse_1('{', {
// x = Position: {expr}
Expand Down
47 changes: 37 additions & 10 deletions src/addons/script/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,8 @@ for_stmt: {
Parse_1(EcsTokRange, {
Expr(0, {
ecs_expr_node_t *to = EXPR;
ecs_script_for_range_t *stmt = flecs_script_insert_for_range(parser);
ecs_script_for_range_t *stmt =
flecs_script_insert_for_range(parser);
stmt->loop_var = Token(1);
stmt->from = from;
stmt->to = to;
Expand Down Expand Up @@ -599,16 +600,29 @@ pair: {

// (Eats, Apples):
case ':': {
// (Eats, Apples): {
Parse_1('{',
// (Eats, Apples): { expr }
Initializer('}',
// Use lookahead so that expression parser starts at "match"
LookAhead_1(EcsTokKeywordMatch, {
// (Eats, Apples): match expr
Expr('\n', {
ecs_script_component_t *comp =
flecs_script_insert_pair_component(
parser, Token(1), Token(3));
comp->expr = INITIALIZER;
EndOfRule;
)
comp->expr = EXPR;
EndOfRule;
})
})

// (Eats, Apples): {
Parse_1('{', {
// (Eats, Apples): { expr }
Initializer('}',
ecs_script_component_t *comp =
flecs_script_insert_pair_component(
parser, Token(1), Token(3));
comp->expr = INITIALIZER;
EndOfRule;
)
}
)
}

Expand Down Expand Up @@ -678,8 +692,9 @@ identifier_flag: {
Parse_1('{',
// auto_override | Position: {expr}
Expr('}', {
ecs_script_component_t *comp = flecs_script_insert_component(
parser, Token(2));
ecs_script_component_t *comp =
flecs_script_insert_component(
parser, Token(2));
comp->expr = EXPR;
EndOfRule;
})
Expand Down Expand Up @@ -750,6 +765,18 @@ identifier_assign: {
LookAhead_2(EcsTokIdentifier, ':',
pos = lookahead;

// Use lookahead so that expression parser starts at "match"
LookAhead_1(EcsTokKeywordMatch, {
// (Eats, Apples): match expr
Expr('\n', {
ecs_script_component_t *comp =
flecs_script_insert_pair_component(
parser, Token(1), Token(3));
comp->expr = EXPR;
EndOfRule;
})
})

// x = Position: {
Parse_1('{', {
// x = Position: {expr}
Expand Down
6 changes: 5 additions & 1 deletion test/script/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,11 @@
"const_assign_empty_initializer",
"const_assign_empty_collection_initializer",
"const_i32_assign_empty_initializer",
"const_i32_assign_empty_collection_initializer"
"const_i32_assign_empty_collection_initializer",
"component_w_match",
"component_w_match_invalid",
"pair_component_w_match",
"component_assign_w_match"
]
}, {
"id": "Template",
Expand Down
199 changes: 199 additions & 0 deletions test/script/src/Eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -10070,3 +10070,202 @@ void Eval_const_i32_assign_empty_collection_initializer(void) {

ecs_fini(world);
}

void Eval_component_w_match(void) {
ecs_world_t *world = ecs_init();

ecs_entity_t ecs_id(Position) = ecs_struct(world, {
.entity = ecs_entity(world, {.name = "Position"}),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});

const char *expr =
HEAD "Foo {"
LINE " Position: match $i {"
LINE " 1: {10, 20}"
LINE " 2: {20, 30}"
LINE " 3: {30, 40}"
LINE " _: {40, 50}"
LINE " }"
LINE "}"
;

ecs_script_vars_t *vars = ecs_script_vars_init(world);
ecs_script_var_t *var = ecs_script_vars_define(vars, "i", ecs_i32_t);

ecs_script_eval_desc_t desc = { .vars = vars };
ecs_script_t *s = ecs_script_parse(world, NULL, expr, &desc);
test_assert(s != NULL);

{
*(int32_t*)var->value.ptr = 1;
test_assert(ecs_script_eval(s, &desc) == 0);
ecs_entity_t foo = ecs_lookup(world, "Foo");
test_assert(foo != 0);
const Position *ptr = ecs_get(world, foo, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 10);
test_int(ptr->y, 20);
}

{
*(int32_t*)var->value.ptr = 2;
test_assert(ecs_script_eval(s, &desc) == 0);
ecs_entity_t foo = ecs_lookup(world, "Foo");
test_assert(foo != 0);
const Position *ptr = ecs_get(world, foo, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 20);
test_int(ptr->y, 30);
}

{
*(int32_t*)var->value.ptr = 3;
test_assert(ecs_script_eval(s, &desc) == 0);
ecs_entity_t foo = ecs_lookup(world, "Foo");
test_assert(foo != 0);
const Position *ptr = ecs_get(world, foo, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 30);
test_int(ptr->y, 40);
}

{
*(int32_t*)var->value.ptr = 4;
test_assert(ecs_script_eval(s, &desc) == 0);
ecs_entity_t foo = ecs_lookup(world, "Foo");
test_assert(foo != 0);
const Position *ptr = ecs_get(world, foo, Position);
test_assert(ptr != NULL);
test_int(ptr->x, 40);
test_int(ptr->y, 50);
}

ecs_script_vars_fini(vars);
ecs_script_free(s);

ecs_fini(world);
}

void Eval_component_w_match_invalid(void) {
ecs_world_t *world = ecs_init();

ecs_struct(world, {
.entity = ecs_entity(world, {.name = "Position"}),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});

const char *expr =
HEAD "Foo {"
LINE " Position: match $i {"
LINE " 1: {10, 20}"
LINE " 2: {20, 30}"
LINE " 3: {30, 40}"
LINE " }"
LINE "}"
;

ecs_script_vars_t *vars = ecs_script_vars_init(world);
ecs_script_var_t *var = ecs_script_vars_define(vars, "i", ecs_i32_t);

ecs_script_eval_desc_t desc = { .vars = vars };
ecs_script_t *s = ecs_script_parse(world, NULL, expr, &desc);
test_assert(s != NULL);

{
*(int32_t*)var->value.ptr = 4;
ecs_log_set_level(-4);
test_assert(ecs_script_eval(s, &desc) != 0);
}

ecs_script_vars_fini(vars);
ecs_script_free(s);

ecs_fini(world);
}

void Eval_pair_component_w_match(void) {
ecs_world_t *world = ecs_init();

ECS_TAG(world, Tgt);

ecs_struct(world, {
.entity = ecs_entity(world, {.name = "Position"}),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});

const char *expr =
HEAD "Foo {"
LINE " (Position, Tgt): match $i {"
LINE " 1: {10, 20}"
LINE " 2: {20, 30}"
LINE " 3: {30, 40}"
LINE " }"
LINE "}"
;

ecs_script_vars_t *vars = ecs_script_vars_init(world);
ecs_script_var_t *var = ecs_script_vars_define(vars, "i", ecs_i32_t);

ecs_script_eval_desc_t desc = { .vars = vars };
ecs_script_t *s = ecs_script_parse(world, NULL, expr, &desc);
test_assert(s != NULL);

{
*(int32_t*)var->value.ptr = 4;
ecs_log_set_level(-4);
test_assert(ecs_script_eval(s, &desc) != 0);
}

ecs_script_vars_fini(vars);
ecs_script_free(s);

ecs_fini(world);
}

void Eval_component_assign_w_match(void) {
ecs_world_t *world = ecs_init();

ecs_struct(world, {
.entity = ecs_entity(world, {.name = "Position"}),
.members = {
{"x", ecs_id(ecs_f32_t)},
{"y", ecs_id(ecs_f32_t)}
}
});

const char *expr =
HEAD "Foo = Position: match $i {"
LINE " 1: {10, 20}"
LINE " 2: {20, 30}"
LINE " 3: {30, 40}"
LINE "}"
;

ecs_script_vars_t *vars = ecs_script_vars_init(world);
ecs_script_var_t *var = ecs_script_vars_define(vars, "i", ecs_i32_t);

ecs_script_eval_desc_t desc = { .vars = vars };
ecs_script_t *s = ecs_script_parse(world, NULL, expr, &desc);
test_assert(s != NULL);

{
*(int32_t*)var->value.ptr = 4;
ecs_log_set_level(-4);
test_assert(ecs_script_eval(s, &desc) != 0);
}

ecs_script_vars_fini(vars);
ecs_script_free(s);

ecs_fini(world);
}
Loading

0 comments on commit 9254323

Please sign in to comment.