Saturday, February 4, 2012

Unable to Compile Prefixed Dart

‹prev | My Chain | next›

Last night I uncovered an exciting little feature of Dart: library prefixes. These little beasties allow me to refer to classes locally as being part of a namespace (e.g. "Views"):
#import('Collections.Comics.dart', prefix: 'Collections');
#import('Views.Comics.dart', prefix: 'Views');
#import('Views.AddComic.dart', prefix: 'Views');

main() {

  var my_comics_collection = new Collections.Comics()
    , comics_view = new Views.Comics(
        el:'#comics-list',
        collection: my_comics_collection
      );

  my_comics_collection.fetch();

  new Views.AddComic(el:'#add-comic');
}
This gives me a means to distinguish between my Comics view (prefixed as Views.Comics) and my Comics collection (prefixes as Collections.Comics). Better still, I can still define the classes without the prefixes:
#library('Collection View for My Comic Book Collection');

#import('dart:html');
#import('dart:json');
#import('HipsterView.dart');

class Comics extends HipsterView { /* ... */ }
It is, perhaps, something of a pet peeve, but embedding the type of class in the class name (a class level Hungarian notation) seems wrong. I am in the Views.Comics.dart file--of course, this is a view. My class is extending my MVC library's HipsterView—of course, this is a view. Why should I need to named the class ComicsView?

And so I approve of Dart's solution. In the class definition, I can call it Comics, but where clarity necessitates, I can prefix it as Views.Comics. Except it does not work. As noted last night, importing two libraries into the same class throws an error (from the next line):
Internal error: 'http://localhost:3000/scripts/comics.dart': Error: line 5 pos 1: 'Views' is already defined
If the latest Dartium ever finishes compiling, I will give it a try to see if this has since been resolved. In the meantime, I can check to see if compiling this into Javascript will work. After grabbing the most recent build, I try compiling:
➜  scripts git:(mvc) frogc main.dart
error: conflicting members for "Views"
main.dart:3:1: error: conflicting members for "Views"
#import('Views.AddComic.dart', prefix: 'Views');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: conflicting types for "Views"
error: conflicting types for "Views"
compilation failed with 3 errors
Compilation failed
Dang. Dart really not seem to want to allow multiple class in the same prefix.

But guess what, Dart? I have access to you source code. After grep'ing through the dark-sdk, I find that error message in ./lib/frog/library.dart:
// TODO(jimhug): Should be merged with new lookup method's logic.
  Type findTypeByName(String name) {
    var ret = types[name];

    // Check all imports even if ret != null to detect conflicting names.
    // TODO(jimhug): Only do this on first lookup.
    for (var imported in imports) {
      var newRet = null;
      if (imported.prefix == null) {
        newRet = imported.library.types[name];
      } else if (imported.prefix == name) {
        newRet = imported.library.topType;
      }
      if (newRet != null) {
        // TODO(jimhug): Should not need ret != newRet here or below.
        if (ret != null  && ret != newRet) {
          world.error('conflicting types for "$name"', ret.span, newRet.span);
        } else {
          ret = newRet;
        }
      }
    }
    return ret;
  }
Unfortunately, I am unable to figure that one out. Although it seems that the classes need to be identical (ret != newRet). I will continue investigating....

Update: In the case where I hit the world.error, both ret and newRet are DefinedType objects, but both point to null. They themselves are not null, but they point to a null object, which makes some kind of sense since this is a prefix, not a class or object of some kind. I still cannot use this information to get it to compile.

Update 2: If add a guard to prevent the world.error:
if (newRet != null) {
        // TODO(jimhug): Should not need ret != newRet here or below.
        if (ret != null  && ret != newRet) {
          if (newRet.name != null) {
            world.error('conflicting types for "$name"', ret.span, newRet.span);
          }
        } else {
//...
then I end up with a "conflicting member" error:
error: conflicting members for "Views"
main.dart:3:1: error: conflicting members for "Views"
#import('Views.AddComic.dart', prefix: 'Views');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I think that is about as much as I am willing to dig through this for now. I may pick back up in the morning...


Day #286

No comments:

Post a Comment