wren-lang / wren

The Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.
http://wren.io
MIT License
6.86k stars 550 forks source link

Proposal: Header files / header of a file for Modules #91

Closed kmarekspartz closed 9 years ago

kmarekspartz commented 9 years ago

A wrenh file could give the structure of the corresponding wren file:

module Collections {
   class Set {
     new(sequence)
     union(other)
     // ...
   }
}

This could also go at the top of a file, with something like a where after the last closing bracket a la Haskell.

I believe this could satisfy #79's goals of 1, 2, 3, 4 (with two passes, loading the header declarations first and then the definitions), 5, 6, and possibly 0 and 7.

munificent commented 9 years ago

Interesting. My gut tells me that:

  1. Having separate "header" files would turn people off. They aren't exactly the most-loved feature of C/C++. :)
  2. Having to list all of the members of your (public) classes twice would turn people off. We're supposed to be a lightweight scripting language, after all.

But, like you say, we could address 1 by putting this at the top of the file. And we could address two by just not including the class bodies. After all, members are already dynamically dispatched, so they don't need to be declared. All we need to know at compile time is the top level names. In your example here, it's just Set.

Wren has an existing problem that the top level isn't mutually recursive. In other words, this has a compile error:

class Foo {
  foo { new Bar }
}

class Bar {
  bar { new Foo }
}

Not handling this is obviously super lame. I just haven't come up with a good solution. One option would be to have forward declarations. Something roughly like:

declare Bar

class Foo {
  foo { new Bar }
}

class Bar {
  bar { new Foo }
}

I wonder if we could solve both modules and this with a similar solution? So you could forward declare a name, and also choose to export that from the module. We could possibly constrain the grammar such that declarations have to come before everything else so that by the time we start handling circular imports, we know all the names.

There might be a nice solution in there, but I'm not sure. There's still the question of when you import a module, do you get a batch of names defined in your scope, or do you get a single object and everything you access from the module is dynamically dispatched based on that?

What did you have in mind for that here?

kmarekspartz commented 9 years ago

I guess what I'm describing is more like interfaces than modules. I'm still working on wording the SML-inspired proposal, which extends this one, but I wanted this one to stand on its own.

munificent commented 9 years ago

I'm closing this out because I've landed basic support for modules and imports, but feel free to re-open this if you want to refine what I have.