Code:

Causerie: A Wishlist

Previously: Causerie Begins With...

When beginning a project, after you have decided the goal, it is often helpful to brainstorm a list of ways in which the goal will be fulfilled: a wish list of features. The advantages are many: it helps you to chart your course -- how you will achieve the end result, it provides focus, it can be used to delegate tasks, and so forth. The danger is of feature creep: that you will add so many features that your project becomes mired in wishes before it even begins.

To prevent just such a thing, my first wish is that the project remains manageable by a single person, if need be; otherwise, it will never see the light of day and any other features that I'd like to add will be moot. Features that might require the investment of another developer -- or a whole community of them -- are best left until after the first release. After all, how do you attract a community of developers if you can't prove the thing works? This doesn't mean that you can't wish for the moon when developing a wishlist of features, only that you might have to accept that you must first build the rocket to reach it.

The following wish list will make more sense now that the appropriate background has been drawn for you. The list represents the things that I would like to have in the language; these are not all necessarily features that will be added -- and if they are, they may not all be added for the first iteration of the language -- but it provides a good starting point. It will help to define the design of the parser and executor back-ends. And so, without further ado, the list:

The List

  1. The programming and initial release of the language should be within the power of a single person.
  2. The syntax of the language will derive from Smalltalk.
  3. The language will be simple, elegant, and powerful.
    • Power here refers to speed of execution and relatively easy access to low-level hardware, if needed. Code should be optimized as much as possible: short-circuit boolean evaluation where possible, pseudo-classes that exist only in the compiler and translate to native code, etc.
    • Simplicity and elegance refer to a minimalist design approach:
      • Each class should represent exactly one idea; we want modular classes rather than monolithic classes.
      • No operators should be redefined just for the sake of redefining operators.
      • No multiple inheritance is allowed, but interfaces are.
      • No garbage collection code is allowed; the programmers can clean up their own $*%! messes. However, managed references might be okay (since GObject uses reference counting anyway).
      • No properties are allowed, but accessor and mutator methods are.
    • Simplicity and elegance will be favored over power, if ever the three should come into conflict.
    • Any new features added to the language or runtime must be necessary, and they must be implemented in a manner that is simple, elegant, and powerful.
  4. The language should compile somehow to machine code.
    • It will initially condense into C code that relies on GLib/GObject, much as Vala does, making the initial implementation less of a compiler and more of a glorified C preprocessor -- but let's not argue over semantics.
    • It may be ported to LLVM at some point in the future and become a real boy.
    • At the very least, it should produce code that can execute on Linux, on Windows and (sigh) on MacOS. (Mac users: nothing personal, but a multi-million dollar company like Apple could have afforded to make developing for your platform a lot easier than they did). Targeting GCC should make this possible.
    • It should be capable of producing console and graphical applications. GTK+ wrapper libraries will be written, but they will not be part of the runtime, which means that the programmer is free to choose another UI library. However, GTK+ seems like a natural fit since we are already tying the initial implementation to GLib/GObject and GIO.
    • Aside from the runtime library, it should not require any link libraries. If dynamic libraries are referenced, the runtime will use dlopen() and dlsym() behind the scenes (as Free Pascal does) rather than requiring a link library. However, since the language condenses to C, it is still possible to link to other libraries at compile time.
  5. It should provide a full-featured runtime library that includes:
    • Classes to represent the intrinsic types available in other languages -- integers, floating-point values, managed strings, etc.
    • Classes to represent some helpful objects, such as binary trees and dictionaries.
    • Classes for streaming I/O.
    • Classes for network access.
    • Classes for threaded programming.
    • Much of the above is accomplished by tying the language to GLib/GObject and GIO, at least for the time being.
      • We will look into statically linking GLib/GObject and GIO, to eliminate some of the DLL hell.
  6. From the second iteration onward, it should be self-hosting compiler: one written in its own language that compiles itself.
  7. The parser and executor should be modular, so that they can be swapped out for others:
    • One for syntax highlighting
    • One to emit documentation for code
    • One for interpreting the language rather than compiling it
    • One to preprocess the source
    • One to emit C code