This page is no longer maintained — Please continue to the home page at www.scala-lang.org

XML Literals Abstraction

4 replies
daniel
Joined: 2008-08-20,
User offline. Last seen 44 weeks 15 hours ago.
As part of my ongoing work on Anti-XML, I'm looking at making the XML literals generic (so that they aren't just hard-coded to generate scala.xml).  Just to be clear, I'm talking about the literals, not the extractors.  People who use XML pattern matching are already dealing with enough cruftiness, I don't feel a need to make any extra effort on their part.

One of the core imperatives is that literals will syntactically work the same as they always have, and they will by default general scala.xml structures (again, as they always have).  Thus, this is a purely additive change, rather than anything which would disrupt existing semantics.  The way I want to do this is with implicits (what else?).  Here's a taste of what I'm thinking:

type NodeBuilder[N]

trait ElemBuilder[N, E <: N] extends NodeBuilder[N] {
  def apply(ns: Option[String], name: String, attrs: Seq[(Option[String], String, String)], children: Seq[N]): E
}

object ElemBuilder {
  import xml._
 
  implicit object ScalaXMLElemBuilder extends ElemBuilder[Node, Elem] {
    def apply(ns: Option[String], name: String, attrs: Seq[(Option[String], String, String)], children: Seq[Node]) = {
      val md = attrs.foldRight(Null: MetaData) {
        case ((None, key, value), tail) => new UnprefixedAttribute(key, value, tail)
        case ((Some(pre), key, value), tail) => new PrefixedAttribute(pre, key, value, tail)
      }
      Elem(ns getOrElse null, name, md, children: _*)
    }
  }
}

trait TextBuilder[N, T <: N] extends NodeBuilder[N] {
  def apply(text: String): T
}

object TextBuilder {
  import xml._
 
  implicit object ScalaXMLTextBuilder extends TextBuilder[Node, Text] {
    def apply(text: String) = Text(text)
  }
}

Incidentally, consider this a long-form request (again) for dependent method return types.  :-)  BTW I'm not sold on the idea of separate typeclasses here, I just did it to try to minimize the number of type parameters required.

Basically, I'm going to modify the XML literals support to generate code which delegates to these implicit factories, rather than immediately instantiating scala.xml objects.  The advantage to this particular implicit approach is it's very easy to override even at a framework level.  For example, Anti-XML would override these implicits in its package object, and so anyone who imports antixml._ would immediately see their XML literals generating Anti-XML structures, all in a syntactically transparent way.

Thoughts?  I haven't yet gotten too deeply into the actual compiler sources, so it's possible that there are several other methods which are required here.  I'll take any feedback, but I'm mostly interested in opinions on the implicit approach itself.

Daniel
Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: XML Literals Abstraction

On Mon, Jul 25, 2011 at 1:21 AM, Daniel Spiewak wrote:

> Thoughts?  I haven't yet gotten too deeply into the actual compiler sources,
> so it's possible that there are several other methods which are required
> here.  I'll take any feedback, but I'm mostly interested in opinions on the
> implicit approach itself.

I like it.

XML literals are currently desugared during parsing [1], and child
elements are handled type cased in NodeBuffer [2]. I'm not too sure
where Predef.$scope is conjured from.

scala -Xprint:parser -e "{}"

{
new xml.Elem(null, "xml", xml.Null, $scope, ({
val $buf = new xml.NodeBuffer();
$buf.$amp$plus({
{
new xml.Elem(null, "y", xml.Null, $scope)
}
});
$buf
}: _*))
}

[1] https://github.com/scala/scala/blob/551dd91342bc1f1ececeb3ae30e5fa3c01c9...
[2] https://github.com/scala/scala/blob/551dd91342bc1f1ececeb3ae30e5fa3c01c9...

daniel
Joined: 2008-08-20,
User offline. Last seen 44 weeks 15 hours ago.
Re: XML Literals Abstraction

Been spending time with that exact code today. If I can find the canonical listing of Scala's AST constructors, this might actually be doable on a sane timeline! In other words, things are less terrifying than I was expecting.

Daniel

On Jul 24, 2011, at 11:00 PM, "Jason Zaugg" wrote:

> On Mon, Jul 25, 2011 at 1:21 AM, Daniel Spiewak wrote:
>
>> Thoughts? I haven't yet gotten too deeply into the actual compiler sources,
>> so it's possible that there are several other methods which are required
>> here. I'll take any feedback, but I'm mostly interested in opinions on the
>> implicit approach itself.
>
> I like it.
>
> XML literals are currently desugared during parsing [1], and child
> elements are handled type cased in NodeBuffer [2]. I'm not too sure
> where Predef.$scope is conjured from.
>
> scala -Xprint:parser -e "{}"
>
> {
> new xml.Elem(null, "xml", xml.Null, $scope, ({
> val $buf = new xml.NodeBuffer();
> $buf.$amp$plus({
> {
> new xml.Elem(null, "y", xml.Null, $scope)
> }
> });
> $buf
> }: _*))
> }
>
>
> [1] https://github.com/scala/scala/blob/551dd91342bc1f1ececeb3ae30e5fa3c01c9...
> [2] https://github.com/scala/scala/blob/551dd91342bc1f1ececeb3ae30e5fa3c01c9...

soc
Joined: 2010-02-07,
User offline. Last seen 34 weeks 5 days ago.
Re: XML Literals Abstraction

Hi Daniel,

great work!

> Thoughts? I haven't yet gotten too deeply into the actual compiler sources,
> so it's possible that there are several other methods which are required
> here. I'll take any feedback, but I'm mostly interested in opinions on the
> implicit approach itself.

I would prefer a more "pluggable" approach, where it would be possible
to not use/ship _any_ implementation at all => This would make XML
support/literals optional and I would highly appreciate that, because
that would be a great step towards more modularity. (More importantly,
this would be a great PR move in times of "OMG, Scala is so complex".)

In an ideal world i could imagine having a separate scala-xml.jar
(like scala-swing.jar) which can be easily replaced by other "XML
providers" like anti-xml.jar; and a commandline switch to the compiler
like "-xmlprovider=..." which would point to scala-xml by default.

BTW, would it be possible to rename the package? I would expect some
JSON library behind "Anti-XML" ... would it be possible to have
something like scalax.xml?

Bye

daniel
Joined: 2008-08-20,
User offline. Last seen 44 weeks 15 hours ago.
Re: XML Literals Abstraction
I would prefer a more "pluggable" approach, where it would be possible to not use/ship _any_ implementation at all => This would make XML support/literals optional and I would highly appreciate that, because that would be a great step towards more modularity. (More importantly, this would be a great PR move in times of "OMG, Scala is so complex".)

In an ideal world i could imagine having a separate scala-xml.jar (like scala-swing.jar) which can be easily replaced by other "XML providers" like anti-xml.jar; and a commandline switch to the compiler like "-xmlprovider=..." which would point to scala-xml by default.

I think we would all prefer more pluggable XML support.  Unfortunately, there are two problems with this.  First, we need to preserve backwards compatibility.  Removing XML literals is a pretty big change, and I would imagine something that would need to be deferred for a major version update (e.g. 3.0).  Second, the compiler is pluggable, yes, but not at the parser level.  XML literals are like for-comprehensions, just a trick of the parser (well, and the pattern matcher).  Any pluggable support would need to be able to hook into the parser, and this is not currently possible.  Even theoretically, this is a very difficult thing to pull off.  There's a lot of research on pluggable and composable parsers, but no one really has a satisfactory approach yet (though in practice, parser combinators / PEG works pretty well).

So, I wouldn't expect to see pluggable XML support any time soon.  :-)  And unfortunately, we need to leave the default backend as scala.xml.

BTW, would it be possible to rename the package? I would expect some JSON library behind "Anti-XML" ... would it be possible to have something like scalax.xml?

The package name of Anti-XML will definitely change when we incorporate it into the standard library.  That's not going to happen in the 2.10 timeframe though (unlike the more flexible literals, which I hope to finish in time).

Daniel

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland