Repository navigation
[script] Resolve names in the type pass from the entity scope chain, like evaluation - #2
Closed
Andrew Gazelka (andrewgazelka) wants to merge 1 commit into
Closed
Andrew Gazelka (andrewgazelka) wants to merge 1 commit into
Andrew Gazelka (andrewgazelka) wants to merge 1 commit into
Conversation
…ike evaluation The type pass kept v->parent at the outer parent while typing entity scopes, so names that only exist in the world (e.g. created by a previous script) in an enclosing scope did not resolve, and were reported as unresolved references. Set v->parent to the existing world entity of each entity scope before typing it, as evaluation does.
Member
Author
|
Superseded by the upstream PR SanderMertens#2380 (SanderMertens#2380). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
A game runs several scripts in sequence with
ecs_script_run:The second script fails with
unresolved reference 'steel'. The error comes from the type-check visitor:flecs_script_type_report_unresolved←flecs_script_type_lookup←flecs_script_id_elem_lookup.Root cause
flecs_script_symbol_lookupfirst tries the type pass's symbol table, which only holds names declared by this script. It then falls back to the world:FlecsMeta, then a recursive lookup fromv->parent, thenusingpaths, then the lookup action. Evaluation setsv->parentto each entity as it enters that entity's scope. The type pass did not:v->parentstayed at the outer parent of the script for the whole walk. As a result, names in an enclosing scope that exist only in the world were never found. Here that isstructure.prefabs.steel, created by the previous script. Names declared in the same script did resolve, because they are script symbols.Fix
flecs_script_type_entitynow callsflecs_script_type_push_parentbefore typing an entity's scope and restores the previous parent afterwards:v->parentis set to it. The entity is found either from the node's symbol slot or withecs_lookup_path_w_sep(world, v->parent, name), the same lookup evaluation uses to find or create it.v->parentis kept. Evaluation will create it with no children, so a recursive lookup from it gives the same result as a lookup from its parent.parent_missingflag stops them from being looked up by name under the wrong parent.With this, the type pass resolves names through the same chain as evaluation: this script's symbols, then
FlecsMeta, the scope chain,usingpaths, and the lookup action.The code that already set
v->parentexplicitly inside the type pass is unchanged, since it sets the parent from the owner itself before evaluating: export const, template, module, and type entities.distr/flecs.chas the same change.Tests (
test/script, Eval)New tests. Each runs two scripts in sequence and fails without the fix:
scoped_prefab_inherit_from_prev_script:structure { prefabs { Prefab steel { Foo } } }, thenstructure { prefabs { Prefab steel_a992 : steel {} } }. Checks the IsA relationship, the prefab, and the inheritedFoo.scoped_entity_ref_from_prev_script:(MadeOf, steel)resolving tostructure.materials.steel, created by the earlier script.scoped_component_from_prev_script:struct Profile(...)declared instructure.componentsby script 1 and set asProfile: {...}in the same scope by script 2. Checks the values.nested_scope_component_from_prev_script: the component is declared instructureby script 1 and used one scope deeper, instructure.prefabs.mullion, by script 2.Behaviour change, two existing tests updated.
const_w_component_in_scope_expr_in_scopeandconst_w_component_and_entity_in_scope_expr_in_scopeasserted thatparent.Position(andparent.e), created from C, do not resolve insideparent { const pos = e[Position]; foo { Position: pos } }in a script. That assertion only held because of this bug. Evaluation looks up names recursively fromparent.foo, which findsparent.Position, and the..._in_modulecounterparts already passed. Both tests now assert that the script succeeds and thatparent.foogetsPosition {10, 20}.Results
distr/flecs.ccompiles with-Wall -Wextra -Werror.