Vala and the comma operator

One of the more interesting parts of working on a Vala project is occasionally having to read through the C source the Vala compiler generates.  Sometimes it’s to investigate a bug (maybe your own, maybe the compiler’s) and sometimes it’s just out of curiosity.

Personally, I think the C code Vala produces is pretty darn good as far as machine-generated code goes.  (And I’ve seen some horrible machine-generated code, not including obfuscators and their ilk.  Which reminds me, have I ever told you about when I met Phil Katz?  Another time.)  Certainly I feel I could produce much prettier code by hand, but that’s the point: I would have to do it by hand.  A lazy programmer is a good programmer.

Take a look at this typical example of Vala’s generated C code:

gboolean dimensions_has_area (Dimensions *self) {
    gboolean result;
     gboolean _tmp0_ = FALSE;
     if ((*self).width > 0) {
         _tmp0_ = (*self).height > 0;
     } else {
         _tmp0_ = FALSE;
     }
     result = _tmp0_;
     return result;
}

If an interview candidate at Yorba put this up on the whiteboard, I imagine the first thing we’d ask would be, “Ah … anything you think you could do to clean up this function?”

This isn’t to knock Vala or the compiler or the wonderful work Jürg and Team Vala have done.  And yes, I know, gcc will optimize this down to machine code that would be pretty much like the machine code it would produce if I hand-coded this.  And, of course, unless this is in hot loop (which it’s not, last time I checked), none of this matters anyway.

In short, I lose zero sleep over this.

But consider this line, which is also not atypical:

scaled = (dimensions_floor ((_tmp2_ = (dimensions_init (&_tmp0_, (gint) round (scaled_width), (gint) round (scaled_height)), _tmp0_), &_tmp2_), (_tmp3_ = (dimensions_init (&_tmp1_, 1, 1), _tmp1_), &_tmp3_), &_tmp4_), _tmp4_);

Ah … okay, hold on.  Don’t run off.  It’s not as bad as you think.  It’s just that this makes much more sense to the C compiler than it does to you.

My advice to anyone who dives into Vala’s generated code is to study up on the comma operator.  I suspect most programmers (maybe 98% of them!) have never used the comma operator outside a for loop, and even then, rarely.  Most of them would say that the comma operator is only used to perform multiple statements (actually, “operands” in the parlance) on a single line of code.  That is, it’s a handy way when writing a for loop to squeeze in multiple statements inside each of its three parameters.

Which is true, save for one thing: With the comma operator, the statement as a whole evaluates to the final operand.  Thus, the initializers in this for loop evaluate to 42:

for (i = 0, j = 42; i < j; i++)

The initializer isn’t being assigned to anything, so we don’t notice, so we never learn.

Looking back over that C code up there, mentally weed out the _tmp0_, _tmp1_, etc. and see it for what it is: Initializing two dimensions structs (one goes into _tmp2_, the other into _tmp3_), which are passed to dimensions_floor as parameters, which puts its result into _tmp4_ (whose address is passed to dimensions_floor as its third parameter).  The final operand of the comma operator is, in fact, _tmp4_, which then is returned to scaled.  The comma operator makes all this happen.

Here’s that line in Vala, by the way:

Dimensions scaled = Dimensions((int) Math.round(scaled_width), (int) Math.round(scaled_height)).floor();

Shotwell 0.7.2 and gexiv2 0.2.1 released

Yorba has released Shotwell 0.7.2, an update to our digital photo
organizer.  This release includes crucial fixes and translation updates.  It’s highly recommended that all
users upgrade.

This release includes the following:

  * Fixed major startup problem when the user’s Pictures directory is actually
    a symbolic link.
  * Fixed potential crasher when the user’s Pictures directory contains a
    large number of subdirectories.
  * No longer asking if copying or linking if importing from Pictures directory
    (which will always be linked).
  * Fixed update problem when using an external editor on a photo that was
    edited externally in an earlier session.
  * Various bug fixes.
  * Updated translations.

In addition, Yorba has released an update to our Exiv2 GObject wrapper library, gexiv2 0.2.1.  (This library is a requirement for Shotwell.)  This update fixes a bug where a photo file with malformed EXIF could cause a crash.  It’s highly recommended that all users upgrade.

Download a source tarball from the Shotwell home page at:
http://www.yorba.org/shotwell/

Download a source tarball from the gexiv2 home page at:
http://trac.yorba.org/wiki/gexiv2

Binaries for Ubuntu Lucid and Maverick are available at Yorba’s Launchpad PPA:
https://launchpad.net/~yorba/+archive/ppa

Bruno Girin on importing photos from other apps to Shotwell

Bruno Girin, author of the F-Spot import subsystem now shipping in Shotwell 0.7, has written a fantastic blog post on his architecture and how to write import code for other photo applications.  He mentions importing from Picasa, which we certainly are interested in doing at some point.  Bruno has done quite a bit of database work and his thoughts and approach are worth a read for those insights alone.