Merge scope hierarchy for evaluation #2151
Draft
+268
−156
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.
Description of the problem
The evaluateExpr func in the vm pkg recursively evaluate expressions. If you want to evaluate this:
a = [loki.write.endpoint.receiver]
the [loki.write.endpoint.receiver] will be represented by nested structs:
The evaluate will go through the nesting recursively and when it arrives at the IdentifierExpr, it will use the scope to look it up.
The scope looks like this:
The Lookup will check whether the identifier is in the variables. Here it matches "loki" so it return the associated map:
Then the recursion unfolds because "write" will match and it will return "endpoint" which will also match and return the receiver object.
During the lookup, if "loki" would not have been found in the scope, it would have looked up at the parent scope recursively till there is a match. If there is no match and no more parent then it's an error.
The problem with this process is that if you have the following:
Scope:
And you want to evaluate the expression:
a = [loki.write.endpoint2.receiver]
The algorithm will match with the wrong path because it will match "loki" and only at the last AccessExpr it will realise that "endpoint" does not match with "endpoint2" and it will throw an error.
This was not a problem so far because the ParentScope is only used for the ModulePath AFAIK. But now I'm using it for the foreach because unlike modules that uses "arguments" I think that it's nicer if the components in the foreach have access to the outside:
Solution
This solution gets rid of the parent scope aed merges the current scope with the one built for the component. I could not find a way to change it easily in syntax pkg. Solving it in the value_cache seemed easier and safer (thanks @rfratto for the hint).