OK. I fixed the issue, but there’s a couple of loose ends:

1. I don’t know how to add unit tests for these cases. In the current unit 
tests, I see “getNode” and “getVariable” being used. I don’t know the logic in 
setting up tests.
2. I’m not quite sure what "parentNode.getChild(0)” does. What is the parent 
node and will this cause my second case of e.employee.(1 == @id) to fail? 
Removing the check against firstChild caused the testXMLFilterWithAttribute 
test to fail because it prepended “node.” to “length()”.

P.S. I finally got debugging from Eclipse working on the compiler, so hopefully 
I’ll have a much easier time fixing compiler issues in the future. :-)

Thanks,
Harbs

> On Aug 7, 2018, at 10:51 AM, Harbs <harbs.li...@gmail.com> wrote:
> 
> Well, it looks like I was wrong.
> 
> I just tested the following in Flash, and then both give the same results 
> (i.e. return the attribute):
> 
> var emp = e.employee.(@id == 1).@name; // name of employee with id 1
> var foo = e.employee.(1 == @id).@name; // name of employee with id 1
> 
>> On Aug 7, 2018, at 10:27 AM, Harbs <harbs.li...@gmail.com> wrote:
>> 
>> Your example does not seem to be right to me.
>> 
>> Here’s the overview of how filters are supposed to work from the spec:
>> 
>>> Overview
>>> When the left operand evaluates to an XML object, the filtering predicate 
>>> adds the left operand to the front of the scope chain of the current 
>>> execution context, evaluates the Expression with the augmented scope chain, 
>>> converts the result to a Boolean value, then restores the scope chain. If 
>>> the result is true, the filtering predicate returns an XMLList containing 
>>> the left operand. Otherwise it returns an empty XMLList.
>>> When the left operand is an XMLList, the filtering predicate is applied to 
>>> each XML object in the XMLList in order using the XML object as the left 
>>> operand and the Expression as the right operand. It concatenates the 
>>> results and returns them as a single XMLList containing all the XML 
>>> properties for which the result was true. For example,
>>> 
>>> var john = e.employee.(name == "John"); // employees with name John
>>> var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with 
>>> id's 0 & 1
>>> var emp = e.employee.(@id == 1).name; // name of employee with id 1
>>> 
>>> The effect of the filtering predicate is similar to SQL’s WHERE clause or 
>>> XPath’s filtering predicates.
>>> For example, the statement:
>>> 
>>> // get the two employees with ids 0 and 1 using a predicate
>>> var twoEmployees = e..employee.(@id == 0 || @id == 1);
>>> 
>>> produces the same result as the following set of statements:
>>> // get the two employees with the ids 0 and 1 using a for loop
>>> var i = 0;
>>> var twoEmployees = new XMLList();
>>> for each (var p in e..employee) {
>>> with (p) {
>>>   if (@id == 0 || @id == 1) {
>>>     twoEmployees[i++] = p;
>>>   }
>>> }
>>> }
>> 
>> The question is what is "the front of the scope chain of the current 
>> execution context”? I’m pretty sure that means the start of sub-expressions. 
>> I don’t see how that can apply to the right-hand of comparison expressions. 
>> There is nothing in the spec about figuring out if a part of an expression 
>> is referring to XML or XMLList.
>> 
>>> On Aug 7, 2018, at 9:45 AM, Alex Harui <aha...@adobe.com.INVALID> wrote:
>>> 
>>> I don't get what portion of the spec has to do with whether we append 
>>> "node" to various expressions.  IMO, the changes I made only affect 6b.  6a 
>>> is handled by generating a function with "node" as the parameter (because 
>>> node is list[i] in the spec).  The task in 6b is to correctly evaluate any 
>>> e4x filter expression.  I'm not sure what the limits are on what you can 
>>> have in a filter expression, but if you can have just plain "@app" anywhere 
>>> in the filter expression, I don't believe scoping rules would know to apply 
>>> that to the "node" parameter without generating the "node" before "@app".
>>> 
>>> There is a chance that the Flex Compiler was using "magic" to generate the 
>>> "node" and really should have reported an error.  I do remember being told 
>>> that the filter function can be "anything".  Even:
>>> (var foo:int = @app.length(); foo > @bar.length())  
>>> 
>>> If there are actual rules in the spec about evaluating the expression, that 
>>> might apply to how we handle these expressions, otherwise I think the right 
>>> thing is to resolve each expression and if the expression does not resolve 
>>> to anything else, assume that it applies to the node.   I know the logic in 
>>> EmitterUtils.writeE4xFilterNode isn't covering all cases.  It is trying to 
>>> see what the expression resolves to, and returns false for known conditions 
>>> (like a member of a class).  Just make it return false for your case (and 
>>> feel free to add that case to the tests).  Eventually we'll have enough 
>>> cases to either call it "good enough" or figure out a better way to 
>>> determine when the expression applies to "node".
>>> 
>>> My 2 cents,
>>> -Alex
>>> 
>>> On 8/6/18, 11:20 PM, "Harbs" <harbs.li...@gmail.com> wrote:
>>> 
>>>  I just looked at the spec. I think it’s correct to append “node” to the 
>>> first statement of the expression only. The only exception seems to be 
>>> expressions which use boolean expressions (i.e. || or &&) in which case 
>>> each piece of the boolean expression should be considered a self-contained 
>>> expression. So in your example, there are really two filter expressions:
>>>  1. hasOwnProperty("@app”)
>>>  2. @app.length() > 0
>>> 
>>>  Both of those should have node appended to the front, but nothing else.
>>> 
>>>  Here’s the relevant semantics in the spec (the important bit being 6a):
>>> 
>>>> 6. For i = 0 to list.[[Length]]-1
>>>> a. Add list[i] to the front of the scope chain
>>>> b. Let ref be the result of evaluating Expression using the augmented 
>>>> scope chain of step 6a
>>>> c. Let match = ToBoolean(GetValue(ref))
>>>> d. Remove list[i] from the front of the scope chain
>>>> e. If (match == true), call the [[Append]] method of r with argument 
>>>> list[i]
>>>> 7. Return r
>>> 
>>>  Makes sense?
>>> 
>>>  Harbs
>>> 
>>>> On Aug 7, 2018, at 1:39 AM, Alex Harui <aha...@adobe.com.INVALID> wrote:
>>>> 
>>>> In porting Tour De Flex, there were patterns like this (explorerTree is 
>>>> XML):
>>>> 
>>>> explorerTree..node.(hasOwnProperty("@app") && @app.length() > 0)
>>>> 
>>>> The compiler logic before I made any changes yesterday just assumed that 
>>>> the first expression was a reference to the node parameter but other 
>>>> expressions were not, but it looks like the expression "@app.length()" was 
>>>> allowed in Flex as a reference to the node.  So I think the compiler has 
>>>> to determine what expressions evaluate to "nothing" which implies they are 
>>>> references to the node, and what did resolve to something.  This is all 
>>>> new logic and I don't know how to determine all of the test cases up 
>>>> front, so we'll have to keep tuning it as we find patterns that don't work 
>>>> as we want them to.
>>>> 
>>>> In your case, if the expression resolves to a VariableDefinition, that 
>>>> probably means that isn't a reference to node.  Not exactly sure, so you 
>>>> should debug into it to see what the node pattern is and return false.
>>>> 
>>>> Thanks,
>>>> -Alex
>>>> 
>>>> On 8/6/18, 3:28 PM, "Harbs" <harbs.li...@gmail.com> wrote:
>>>> 
>>>> Doesn’t it always need to be a method for it to reference the node?
>>>> 
>>>> I.e. child() should be node.child(), but foo.baz would not.
>>>> 
>>>>> On Aug 7, 2018, at 1:12 AM, Alex Harui <aha...@adobe.com.INVALID> wrote:
>>>>> 
>>>>> Yep, we need more intelligent understanding of when a reference is to the 
>>>>> node or not.
>>>>> 
>>>>> Debug into EmitterUtils.writeE4xFilterNode and figure out the node 
>>>>> pattern you need.
>>>>> 
>>>>> -Alex
>>>>> 
>>>>> On 8/6/18, 3:09 PM, "Harbs" <harbs.li...@gmail.com> wrote:
>>>>> 
>>>>> var folderFolders:XMLList = 
>>>>> assetXML.folder.(child('key').indexOf(folder.key) == 0);
>>>>> var folderImages:XMLList = 
>>>>> assetXML.image.(child('key').indexOf(folder.key) == 0);
>>>>> 
>>>>> Is now compiled as:
>>>>> 
>>>>> var /** @type {XMLList} */ folderFolders = 
>>>>> this.assetXML.child('folder').filter(function(node){return 
>>>>> (node.child('key').indexOf(node.folder.key) == 0)});
>>>>> var /** @type {XMLList} */ folderImages = 
>>>>> this.assetXML.child('image').filter(function(node){return 
>>>>> (node.child('key').indexOf(node.folder.key) == 0)});
>>>>> 
>>>>> “node.folder.key” is not correct. “folder” is a local variable of an un 
>>>>> related object type.
>>>>> 
>>>>> I assume this broke with the recent XML filter changes.
>>>>> 
>>>>> Harbs
>>>>> 
>>>> 
>>>> 
>>>> 
>>> 
>>> 
>>> 
>> 
> 

Reply via email to