Closed Bug 627480 Opened 13 years ago Closed 12 years ago

Figure out what to do with E4X filtering predicates in "E5X"

Categories

(Core :: JavaScript Engine, defect, P5)

Other Branch
defect

Tracking

()

RESOLVED WONTFIX

People

(Reporter: jorendorff, Assigned: brendan)

Details

I think

    x.(a)

should always emit JSOP_NAME for the name `a`, because the innermost scope there is with-like. But we can emit JSOP_GET{LOCAL,ARG,GLOBAL} for that `a`. This is because Parser does not deoptimize tc->lexdeps when leaving an E4X filter-expression the way it does when leaving a withExpression.

The bug is observable:

    var a;
    assertEq(<b><a/></b>.(a).length(), 1);  // fails
Stop-ship purple alert! :-P

/be
Assignee: general → brendan
Priority: -- → P5
Target Milestone: --- → Future
Target Milestone: Future → ---
In case anyone watching cares, I'm very likely to remove filtering predicates from E5X or whatever the proxy-based runtime will be called. For the same reason that there is no 'with' in ES5 strict or Harmony, either...

/be
Brendan: That seems like an overall bad idea to me. I understand that there are issues with namespacing in the predicates similar to those in with blocks, but unlike with statements there's no satisfactory alternative to E4X filter predicates. Perhaps they could be instead implemented with the current node assigned to the this object to remove the namespacing ambiguity?
I wish JavaScript support SQL SELECT with INNER and OUTER JOIN, 
like SQL statements in PL/SQL or T-SQL.
Now E4X is the only thing similar to that we have, and taking out filtering will be almost equivalent to killing E4X.

As I dont have that many examples to show people using E4X for database like processing in JavaScript. But there are lot we can see among Adobe Developers
http://www.google.com/search?q=e4x+filtering

So as Kris suggested we should resolve this by adding "this" or a new keyword "thisNode". Also if possible please add "thisDocument".
So riddle me this: why is code like this, as you suggest (and using |this| for maximum conciseness):

x.(this.@foo || this.@bar == 42)

better than:

x.@foo || x.@bar == 42

?

/be
I know, filtering goes over the whole tree, but that can be handled without the 'with' semantics.

/be
(In reply to comment #5)
> 
> x.@foo || x.@bar == 42

do you mean 
  x.(x.@foo || x.@bar == 42)
?

Are we removing filtering is completely ?
If so how do we do following.


xml = 
<b>
  <a x="1"/>
  <a x="2">
    <c/>
  </a>
  <a x="3">
    <d/>
  </a>
</b>
;


xml.a.(@x==2);


//which gives result as

<a x="2">
  <c/>
</a>
> xml.a.(@x==2);

If I've followed the discussion correctly, you could do:

    xml.a.(@this.x==2)

Dave
(In reply to comment #3)
> Brendan: That seems like an overall bad idea to me. I understand that there are
> issues with namespacing in the predicates similar to those in with blocks, but
> unlike with statements there's no satisfactory alternative to E4X filter
> predicates. Perhaps they could be instead implemented with the current node
> assigned to the this object to remove the namespacing ambiguity?

I don't see why we couldn't add a filter method. The syntax and semantics of E4X is a colossal botch, and writing

    node.filter(function(sub) { return sub.x==2 })

or

    node.filter(function() { return this.x==2 })

is not so onerous. Even better with the upcoming sharp literals:

    node.filter(#() { this.x==2 })

Dave
> The syntax and semantics of E4X is a colossal botch

Meant to say "stx & sem of E4X filter expressions are"

Dave
dherman jumped to the inductive case. The basis case involves you writing "x." or "this." or "something." followed by the E4X property or attribute name and whatever expression it is tested in.

If you're willing to write "x." in front of each such property or attribute, then if you are game to write a few more chars to create a sharp-function wrapper around the whole expression that was in the filtering predicate's parentheses, then XML.prototype.filter method suffices.

E4X has fewer characters but relies on "with". Since folks commenting here seem willing to write "x." left context for prop/attr refs, it seems worth asking if the sharp-function wrapping can be swallowed too.

We could make sharp-function wrapping implicit with new (or existing foo.(bar)) syntax, for sure. It may be that some of the language-integrated query talk on TC39 leads to new (old-new) syntax of this kind. But better yet if we can use just a built-in method, no special syntactic form.

/be
(In reply to comment #11)
> willing to write "x." left context for prop/attr refs, 
> it seems worth asking if
> the sharp-function wrapping can be swallowed too.

I assume sharp-function wrapping wont be an issue.

Brendan, can give examples of proposed syntax.

xml =
<b z="1">
 <a x="1"/>
 <a x="2"><b y="5"/><c><d z="8"/></c></a>
 <a x="2"><b y="3"/><c><d z="7"/></c></a>
 <a x="3"><b y="5"/><c><d z="6"/></c></a>
</b>
;

xml.a.(@x==2 && b.@y==5).c;

gives =====>
<c>
 <d z="8"/>
</c>


What will be equivalent in new syntax for expression
    xml.a.(@x==2 && b.@y==5).c;
to get same result.
(In reply to comment #12)
> What will be equivalent in new syntax for expression
>     xml.a.(@x==2 && b.@y==5).c;

Without sharp:

xml.a.filter(function() { return this.@x==2 && b.@y==5; }).c

With a sharp function:

xml.a.filter(#() { this.@x==2 && b.@y==5; }).c

And if XML objects would be callable then the form could be shortened down to:

xml.a(#() { this.@x==2 && b.@y==5; }).c
The shortest possible change that avoids 'with' semantics is to require a . before each property or attribute of the current node:

  xml.a.(.@x==2 && .b.@y==5).c

A "dot tax" hike, to pay for protection against dynamic scope bugs.

Igor, you need more "this." prefixing ( the "b" refs).

/be
Also, share functions inherit |this| lexically unless they declare it as a parameter, so passing the current node as the first parameter seems better.

/be
(stupid iPad... "sharp" not "share".)
(In reply to comment #14)
>   xml.a.(.@x==2 && .b.@y==5).c

thats not at bad all ...

I assume .parent() will also be supported instead of function::parent()

   xml.a.(function::parent().@z==1 &&  @x==2 && b.@y==5).c;
==>
   xml.a.(.parent().@z==1 && .@x==2 && .b.@y==5).c
Sooooo, my reformed |with| may have a place after all, eh? ;)

But I wonder if we could reconsider whether E4X deserves all that syntactic real estate it grabbed up. There are so many valuable ASCII characters in E4X that I'd love to repurpose. (Not sure whether filter expressions themselves are a problem, but @ is highly desirable, e.g. for metadata.)

Dave
The . prefix is used in other languages. Some AOL acquisition's smarties suggested it ~9 years ago. It is an effective reform (recovery of form: not the Pascal static 'with' but the next best thing), but it's also a bridge too far for Harmony -- if not for "E5X".

@ for decorators has been debated on TC39. Last time we went 'round that block the [meta stuff here] prefix won. I'm indifferent, mostly, but ECMA-357 may lay a claim. Even if not, or perhaps more important anyway: CoffeeScript after Ruby uses @foo for this.foo shorthand. The @ symbol is coveted. This makes me want to avoid using it in Harmony (ignoring E5X) altogether.

/be
> The . prefix is used in other languages.

Well, sure. I didn't claim to have invented VB. ;)

> but it's also a bridge too far for Harmony -- if not for "E5X".

I don't really understand your reasoning; if we introduced the . prefix for E5X, why wouldn't we want to bring back |with|, reformed with the new syntax? It just seems really odd not to. Perhaps you consider it a topic that's likely to trigger TC39 debate? Still, it seems a little arbitrary.

> @ for decorators has been debated on TC39. Last time we went 'round that block
> the [meta stuff here] prefix won. I'm indifferent, mostly, but ECMA-357 may lay
> a claim. Even if not, or perhaps more important anyway: CoffeeScript after Ruby
> uses @foo for this.foo shorthand. The @ symbol is coveted. This makes me want
> to avoid using it in Harmony (ignoring E5X) altogether.

This doesn't make much sense to me either. CoffeeScript and Ruby can use whatever syntax they want. Why should we reserve syntax for them?

But maybe we've strayed too far off topic. I'm not proposing specific syntaxes or specific new features. My point is simply: this bug suggests moving in the direction of self-hosting as much of E4X as a library and possibly even (long-term, anyway) breaking some backwards-compatibility by removing some E4X special forms; if we're doing this, maybe we can entertain the possibility of un-reserving some syntax with the eventual possibility of repurposing.

Dave
Absolutely tc39 will fall into disharmony. But there's another point. ECMA-357 or a successor is *optional*. Just because it has reformed XML filtering predicates does *not* mean ECMA-262 has to have reformed 'with'.

Ideally we would come up with an even better language-integrated query design, and not mess around with 'with'. It's true at least one jQuery templating plugin used 'with' in order "to be like PHP". Yikes!

/be
bhackett is patching this bug as reported over in bug 605200. Morphing...

/be
Summary: E4X filter expressions don't deoptimize name accesses → Figure out what to do with E4X filtering predicates in "E5X"
Per bug 485791, we will build the E5X runtime on top of harmony proxies. This will steer the design toward library methods and functions over special syntax. We will keep the XML literals and some operators and primary expressions such as *.

Since proxies have no invoke trap, we can't compatibly expose methods of XML.prototype as properties of XML instances. As with ES5's Object.create, etc., the prototype methods will move to be functions of the XML constructor: XML.name(x), XML.parent(x), etc.

For this bug, that suggests XML.filter(x, function (n) {...}) (with n for node, the current element being visited). This is overlong, so we should think harder about syntax.

/be
> For this bug, that suggests XML.filter(x, function (n) {...}) (with n for node,
> the current element being visited). This is overlong, so we should think harder
> about syntax.

If we put them in a Harmony module, then they can be imported, so you could write:

    import XML.*;
    filter(x, #(n) {...});

That doesn't look so bad to me. To predict an objection: it's true the "filter" name might also be used by other modules such as an array-utilities module, but Harmony modules are designed to let you locally rename imports to avoid these name collisions.

A more serious objection is that the dot-notation is particularly nice for composing long chains of operations

    x.filter(f).filter(g).filter(h)

They chain more naturally than the functional approach, which bunches up awkwardly:

    filter(filter(filter(x, f), g), h)

That said, I still really don't think E4X deserves much syntax beyond literals.

Dave
Status: NEW → RESOLVED
Closed: 12 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.