Release 13 preparations
So now that templates are basically working, it's time to seriously start plotting the 13th release of the Epoch programming language.
I've hammered out a few basic cleanup and documentation tasks, but there's still a lot of room for improvement. My hunch is that at this point I'll probably set about documenting the code as it stands and churning through as many small refinements as I can stomach. Eventually I'll get horrifically bored with all that and decide to just package the whole thing up and ship it off as a release.
The project's issues list continues to shrink, although there's still a lot of really big-ticket items left on there. I'm personally kind of hung up on the desire to make sure that R13 accurately reflects my dedication to producing a quality piece of software. At the same time, though, I want to ship a release if for no other reason than to commemorate a significant milestone in the language's history.
My perfectionist side insists that all the documentation be complete and a minimum of TODOs be left littering the code, but my pragmatic (and substantially impatient) side will probably win out. In the end, I expect R13 to be mostly a celebration of the improve type system and template engine more than a paragon of clean code design and spotless implementation. I'm OK with that.
Of course, the big question is, after R13, what next?
Epoch has shifted its emphasis over the years several times, depending on what was predominantly motivating me to work on it at various times. There have been a number of lofty goals for the language, with varying degrees of focus depending on the month and year:
- Something, anything but C++
- A powerful metaprogramming language
- A powerful framework for programming DSLs
- Some kind of parallel processing workhorse
- Some kind of distributed computing workhorse
- Just a fun experimental base for prototyping out the way I want to write software, versus how I "have to" write it in contemporary languages
At this point, it's kind of a monster hybrid of all of those goals, and I'm slowly filtering through the apparent contradictions and conflicts until I manage to distill the whole nebulous mess into a coherent language.
That said, here's a glimpse of what I'd like to do.
One of the big questions left for Epoch is how to handle its object model. Type inference and template expansion become undecidable in the presence of certain type system features - namely, subtyping and certain forms of inheritance. This is a problem.
Another big question is how to combine heterogeneous computational hardware support (e.g. GPGPU stuff) with distributed processing with threading with whatever else might come up. This is just a messy question in general.
The last major question is runtime model. Right now things are basically run on a VM, but I've got prototype code in place for JIT compilation to native code via LLVM, which is really cool. Unfortunately, native code generation does not always play well with garbage collection and the other must-have features of the language.
On the face of it, those three questions may seem to lead in very different directions. Is Epoch a native language or a managed one? Does it do really well at modeling object-oriented systems, or does it support rich type inference and minimal explicit type annotation? And how does all the parallel/concurrent processing stuff fit in?
My answer is pretty simple, and dare I say so myself, fairly elegant.
Epoch will not have an object model, nor threading support, nor will it abandon the use of a VM as a runtime model.
Instead, Epoch will divide computational concerns into tasks. A task is simply a self-contained unit of work; think of it like an object, but without the restriction of living in some particular "memory space" or running on some specific thread.
An Epoch task is like a job in a job-based thread pool system. You can't access its memory from outside. All you can do is send it messages. In the same vein, the task cannot communicate to anything outside itself, except by sending messages.
Tasks, by virtue of being self-contained, can therefore be scheduled freely by the runtime. This includes spanning multiple CPU cores, or offloading to a GPU, or even moving them onto an entirely different network node.
A task can be tagged with a "hint" that tells the compiler and runtime how best to handle the task's computational processes. Tag it with [native] and it will be JIT-compiled to native code and run in a lightweight "green thread" on any available CPU core(s). Tag it with [gpu] and it will be compiled instead to a GPGPU program and executed on your graphics hardware. Tag it with [remote] and it can be transparently distributed across a network and load-balanced to an available Epoch-running machine on a whim.
Since tasks are lightweight by default, you can spin up thousands or millions of them with no problems. Tasks completely replace the need for object instances in traditional OO languages, while simultaneously solving a host of other software challenges in a single shot.
It's a pretty weird way to think of software development. I'm not even entirely sure I buy into the idea yet myself. But it feels right, it feels elegant and clean and powerful and robust, and it seems very promising.
The best part is, it won't take much work to make it happen. Almost all of Epoch's history has been slowly moving this direction in some sense or another, and it feels to me like this is just the culmination of years of subconscious rumination on how I really want to think about writing programs.
So what's next after Release 13?
Why, release 14, of course! And R14 will bring with it a few interesting changes:
- entrypoint will become a task
- Task support for green threads will be introduced
- JIT compilation to native code will be enhanced a bit
- Garbage collection will be refined in a few important ways
My idea for the R14 "demo app" is to write a basic raytracer. Via the virtues of JIT compilation and the task model, I think it could trivially harness all available CPU cores on a machine, and perform pretty damn well.
So the R14 goal, in a nutshell, is to deliver a language and a runtime platform that is suitable for performance-intensive software creation.
After that, it's all just polish and features. I'm starting to think this thing might actually become a viable development platform someday!