Fern Development Roadmap
Contributions are always welcome! Make sure to check the Contributor's Notes too if you thinking of writing some code. Some things here might not be up to date, you might want to look at the progress reports for the latest news. Currently, if you want to help, it's best to contact me, either directly, via the devlist, or the discussion list. In case you decide to work on something, please, start a discussion on it!
Fern will form the groundwork for the rest of the project. In general, to learn about the birds-eye view of the architecture, see The Power of Structure/Fern. Also: Fern Overview + KR and Constraints. Not everything is in those writings, some things are yet to be refined and understood, most likely in the course of the development.
The remaining roadmap:
Table of Contents
1. Knowledge-Representation Improvements WIP
1.1. Meta info in slots
An example of meta info: the list of local-only slots. There will be some other stuff too, like advice, probably. But garnet provides some other declarations via it's :declare
syntax, and each thing there will have to be looked into carefully, case-by-case.
Right now, that kind of info is held as part of the kr object and has a special interface. It would be better to just hold these within the slots of the object itself. This would simply be more beautiful, so to speak.
How this is done might depend on the meta info itself. The usual :declare syntax (to be ditched) is read before the slots themselves are read. So, losing the order might mean some things might have to be done dynamically now (some already were).
It's yet to be seen how this is done exactly. Generalized selectors might come in handy here. Some meta slots might be needed early on (like local-slots) and so this feature might have to be implemented soon, but at least in part.
1.2. Advice
Advice like in Emacs. That usually implies: adding a pre-hook, or a post-hook, or around-wrapping. It should be easy to inspect the existing advice and remove/redefine it. Emacs uses named advice to that end.
Several kinds of advice were identified (the following + the constraints). The interface should be as uniform as possible.
1.3. Multi-Methods (value-based)
Clojure does the reasonable thing with its multimethods: it recognizes that it may be really useful to dispatch based on some function of the value, rather than just on its type. I am still thinking through the mechanics of this, but it's clear to me that CLOS/MOP is not to be used for the simple reason of its complexity beyond reason. But I don't find Clojure's approach fully satisfactory either.
As of this moment, I think that a decision tree should be built, where the slots are ordered, and each slot contains a user-supplied decision function. And defining a method would simply add to this tree. Such trees could of course be modeled as schemas, and that will yield a free, easy and inspectable interface to these functions.
Of course, such dispatch won't readily yield good performance, but probably no worse than CLOS. But it can be achieved via declarations where necessary (I am wondering if declare
can be reused for custom stuff, but it's not strictly necessary).
Later on, these functions can be used in constraints as well.
2. 2D Graphics
In general, the point here is to develop an API to draw stuff to a render target. SDL2 will guide some of these API decisions, e.g. when building event objects.
2.1. Linear Algebra and Geometry additions
For geometry, that would be KR equivalents of geometric objects.
Linear algebra just needs to be tested in the course of the development, just to see that everything holds up right.
See Fern Overview + KR and Constraints for details.
2.2. 2D API for geometry + Backend (via SDL)
2.2.1. Geometry
There will be two kinds of geometrical objects: structs (already implemented) and kr-objects (not yet). KR-objects will contain a struct in one of its slots and then provide other slots for easy manipulation. For example, an axis-aligned rectangle struct may be interfaced by it's right/left/top/bottom/width/height slots. But the struct itself only contains two vectors indicating it's two sides. So, theree will be circular constraints to keep everything consistent. Note that the structs themselves are meant to be used immutably.
There should be operations for working on collections of objects. Maybe not now, but at some point.
2.2.2. SDL2 Backend
The backend that implements the API will be SDL2.
There's an SDL2 CFFI bindings library that I have prepared It's a fork of hu.dwim.sdl, but with lispy names and error-handling and some quality-of-life macros. You can check it out here. Note that you need a custom CFFI to run it (just for now, hopefully).
2.3. Event objects + Backend (via SDL)
Objects that hold information about some event like a mouse click or a keypress.
These don't have to be comprehensive, e.g. stuff like joystick input can be safely skipped for now. The window events might not be necessary either: they backend should modify the appropriate properties of the top-level cell directly.
2.4. Text API + Backend (via Pango)
The interface for this will be inspired by Pango. Maybe even simpler (aka skewed or bent text is not exactly a requirement). Only proportional fonts are.
Backend-wise, Pango works well with Cairo, and there's a way to use and SDL surface for Cairo. There is a way to draw Pango directly to an SDL2 texture too, via SDL2_Pango, but the work for that has to be tested as it seems to be pretty new. It shouldn't matter too much for a backend at this point, but the Cairo variant might be easier to install, and is probably better-tested.
3. Cells
This will include contexts, rendering + texture caching, some interplay with the configurations.
Contexts are basically slot-level inheritence relationships, where a slot inherits from some slot in some other object. Should be pretty easy, will probably be done just via some kind of a constraint.
Caching means how you handle textures and drawing.
Configurations: any object added to the tree may have to be autoconfigured.
Shouldn't be anything hairy.
Cells will be done last, or along the course of the development as other features are introduced.
4. Configurations
I have described how these should work in The Power of Structure/Fern/Configurations. Note: I figure the usual inheritence should do the trick if you structure the program correctly, which shouldn't be hard to do. The special kind of inheritence I have described previously (and in the article) is probably not necessary and would only complicate things.
Overall, I don't imagine this should be hard. This will be done after everything else is in order.