I'm about to commit a substantial re-work of the BitC module system; I'm
holding off until I get the spec section re-done. If you have been
writing BitC code, this is going to involve a slight amount of pain. In
many cases, "sed" will be your friend.

CHANGES TO IMPORT

The previous design of the IMPORT form encouraged a certain form of
import hygiene. (import local-name interface-name) let you get to all of
the items exported by the other interface, but also let you control the
pollution of your local name space. This sounds good, but it doesn't
work very well in practice. For example, you were forced to:

  (import lst bitc.list)
  ...
      (lst.car myList)

when what you really wanted (at least in this case) was to say:

  (import bitc.list)
    (car myList)

so we introduced the USE form, where you could say:

  (use lst.car)

but that became visually confusing when what you wanted to say was:

  (use vec.list->vector)

Something about that is just visually awful. I was fixing a test case a
minute ago, and it took me a solid minute to figure out what that meant
so that I could rewrite it into the new form. Also, the existence of a
second form to correct the deficiencies of a first form is almost always
a bad sign.

The hygienic form of import will still exist:

  OLD                           NEW
  (import nm TheInterface)    (import TheInterface as nm)

but there are now two new constructs:

  (import TheInterface)

    This binds all public identifiers exported by TheInterface into the
    local environment, provided there are no binding collisions. It is
    an error if any /nm/ collides.

  (import TheInterface nm ... nm)

    If /nm/ is a public identifier in TheInterface, this binds /nm/
    into the local environment, provide that no collisions occur. It
    is an error if any /nm/collides.

    In place of /nm/, one can write:

        (nm as localNm)

    with the effect that public identifiers in the imported interface
    can be imported using a substitute name in the current unit of
    compilation.

Since the last two forms subsume USE, USE is being dropped from the
language.

I think we probably need a way to say "import everything, but let me
specify re-mappings for just two of the identifiers that are being
imported." That is probably going to require a new keyword, and it isn't
in yet.

So far, the new forms seem much more usable than the old ones.


CHANGES TO HYGENIC ALIASES

I am strongly inclined to drop the ability to *define* a hygienically
imported (dotted) name. If you provide an interface, you certainly ought
to be able to deal with your own name collisions, and the current syntax
is very awkward for the parser to manage. If this change is made,
hygienic names will be legal only in use-occurrences.

Frankly, it may be that hygienic import is of so little value at this
point that we should drop it altogether.


CHANGE TO PROVIDE

The new syntax for PROVIDE is

  (provide TheInterface pubNm ... pubNm)

which the intended meaning that the current unit of compilation exports
bindings for these public names. Note that the names here are the name
**as specified in the interface**, not the local mappings. PROVIDE no
longer implies any importing behavior; the PROVIDE form merely indicates
that the current unit of compilation intends to supply a public binding.

The binding itself is performed **using the local name (alias)**. If the
name has been remapped, this is potentially confusing, because you can
write:

  (import Foo (bar as baz))
  (provide FOO bar)

  ;; baz is an ALIAS. The following supplies a definition for Foo::bar:
  (define (baz x) ...)

I hope that this situation should be rare enough that we should not
worry about it. The provider of an interface probably should not be
remapping names from their own interfaces except in very unusual cases.

shap

_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to