Beginnings of the "Redbol" Module

There have been three areas of backwards compatibility effort so far:

  • r3-legacy - This started as a collection of runtime switches and shim code to revert Ren-C to act like R3-Alpha. Over time the runtime switches were phased out, as more and more adaptation could be accomplished in usermode.

  • warnings - Various constructs were changed to offer warnings or errors. So rather than UNSET? just start acting completely different, it gave a deprecation message.

  • r3-future - This is a shim which would allow an R3-Alpha to be used for bootstrap, so that the bootstrap code could be written in more modern/idiomatic Ren-C.

I've gone ahead and factored out r3-legacy to its own file, %redbol.reb -- the renewed focus of this will be to be Rebol2/Red compatibility.

It's not a module yet, but it makes a pretty good pathological test case of a module...due to how much it alters the system. It wants to export something like UNSET? with the "old" meaning (similar to NULL?), while at the same time use the current meaning within its own implementation. Right now I've just boxed all the definitions inside of something called EMULATE which binds it into lib, but modules may need to offer support for this kind of situation more generally.

Then I've broken out the warnings into %r2warn.reb. There really is overlap with what knowledge it takes to emulate Rebol2 along with what it would take to warn someone writing to new conventions where something might have a confusing new behavior. So it would be nice to have whether there is emulation, warnings, or both... just as options on %redbol.reb. But right now modules don't do parameterizations (beyond versioning) so let's hold that thought.

With the direction headed toward emulation and legacy support coming from files outside the core, I've gone ahead and bitten the bullet and pulled all the support for things like PAREN! or FOREACH or other things. They "weren't causing any trouble", but they were cluttering things. I'd like to see any hypothetical user who would be depending on those definitions to be hacking on %redbol.reb, to be able to pick all or part of what they wanted...and try and start getting the core tightened up so it's easy to see what's there.

There's some really impressive stuff going on here

When you look at the code, it's really pretty awesome. Even something small, like the change to the splicing behavior:

oldsplicer: helper [
    func [action [action!]] [
        adapt :action [
            all [not only | any-array? :series | any-path? :value] then [
                value: as block! value ;-- guarantees splicing
            ;-- fall through to action's normal implementation

append: emulate [oldsplicer :append]
insert: emulate [oldsplicer :insert]
change: emulate [oldsplicer :change]

Ren-C's behavior changed to the point of being able to say appending a PATH! didn't splice unless it was to another path. And here you have a surgical tweak that can reverse this--in usermode. All while giving you the same interface and refinements for the functions.

You can try and imagine yourself what doing this would be like in Rebol2, R3-Alpha, or Red.

Modules are hard and there's a long road ahead, there

We see that JavaScript still doesn't have modules sorted out--and it's been quite a long time with a world of people working on it. Rebol's landscape is even more complex. And modules are very tied up in binding, which still has a lot of open questions.

What I think has to happen is that I have to sit down and look at the fundamentals. I don't see how anything too big can happen too soon, so really it's probably just going to be one feature at a time.


As an interesting note... I found that when I first pitched Redbol it had the funny name of R3/Backward:

R2/Forward is a project created by @BrianH which helps the R2 interpreter run R3 codebases. It works by patching up a few inconsistencies and adding missing features. It ships now in the downloadable R2 executables and is executed by default.

R3/Backward is an analogue which would be run to help R2 code run in an R3 interpreter. The main intention is to serve as a stopgap measure for those trying to run R2 modules under R3 when no R3 equivalent is ready for that well as to serve as documentation of the changes that will need to be made if a porting process is being done.