Grafting the Bootstrap Executable to act as Interim R3C

@rgchris has been between a rock and a hard place... being a Rebol-style code believer with a large corpus, who hasn't been particularly served by either Red or Ren-C. Unwilling to jump ship for Python or other non-Rebol languages, this has kept him rather stuck in a Rebol2 world.

To make the best of a bad situation, he has put forth the idea of branching Ren-C circa two years ago. The intent is not to stay there long term, but to believe that the dynamism of Ren-C is such that future versions will be able to emulate this point if desired (considering I've stated that emulation of Rebol2 is a goal, this would be even easier).

I have mixed feelings about this plan, but his participation is valuable enough to be worth compromising to try it out. So I've patched R3C to be buildable with more up-to-date compilers in "rigorous" mode (I don't like building without all warnings on, and don't feel like having to install old GCC or MSVC to build an older branch).

I've also done a few patches to try and make R3C closer to mainline. So far:

  • COLLECT and KEEP in PARSE - This was a strongly-requested feature by @rgchris, and as such it doesn't make sense to have implemented it and leave it out of R3C. The syntax is different than Red's version, per his request, and it does rollback...which Red also does not.

  • Permissive Group Invisibility - At first I thought this idea wouldn't be useful. But the more I used "invisibles", the more I wanted to be able to group them like any other value. forum post

  • ENBIN and DEBIN - There are many ways to encode integers as binary or decode them. Rebol's attempt to have a "standard" TO BINARY! for integers and TO INTEGER! of a binary wound up being a major pain point in the 32-bit to 64-bit conversion for integers. This would only get worse with arbitrary precision numbers...the next frontier. These dialects may not be the perfect design, but their weird names make them easy to find...and they're pretty good power tools for the purpose. forum post

  • PRINT NEWLINE is allowed - PRINT's attempt to avoid people getting blindsided by print value where value turns out to be something like [format hard drive] led it to be more prickly, so you know it's not the kind of thing to be used with ANY-VALUE!. The compromise of only taking BLOCK! and TEXT! helped keep it from being a generic debug utility...making it a known quantity. Regardless of this, being able to say PRINT NEWLINE looks nice...and have that mean printing one (and only one) newline. forum post

Really here, the idea is to get engagement on the design...and find out what answers would be satisfying to all involved for the main branch. So the measure of that engagement will drive how much I can afford to work on accommodating bugfixes and feature patches onto the branch. But it seems that this is more useful than Redbol--at least to him--at this point in time.

The biggest deviations from Ren-C are:

  • No change to syntax* or range of datatypes from Rebol 3 Alpha (renaming notwithstanding, e.g. STRING! -> TEXT!)

  • Mostly backward-compatible changes to PARSE grammar, with the following changes from the Rebol 3 Alpha PARSE:

    • Returns position following last match.

    • COLLECT/KEEP (the aforementioned—based on Ren-C, not Red's implementation).

There are other things I'm exploring that would ease a transition from Rebol 2 (or other similar interpreters) once I've had a chance to evaluate the test suite.

* based on target usage, permitting leading '@' email values may be an exception here

Due to the bootstrap binaries not running on GitHub actions for reasons unknown, new build executables are needed. This means taking a moment to build a set of relatively versatile executables that don't have unwanted library dependencies and are likely to run everywhere.

I want to use something rather close to the current state...as opposed to what is snapshotted as R3C at this moment.

It is a win-win scenario if we hammer out a snapshot and maintain usable binaries for it. You have a binary that changes only when you want it to. We commit to keeping in sync and available for bootstrap, and have a shared stake in those executables having a certain minimum utility.

The small bit of R3C work so far hasn't been wasted; as it has meant inventorying and reviewing changes. You've learned a little about what it takes to patch the code, and that is good. You hopefully are clearing your mind of the patently false notion that your opinions aren't considered or important. :see_no_evil:

One of the biggest trip-ups you mentioned...that of the frustrating behavior of "voidification" of branches...is gone now. Corrupting branch results as a default behavior is no longer on the table. So whatever mechanic powers ELSE and THEN won't be any worse than it is done now via the null isotope answer...even if that approach evolves.

I think returning PARSE's default behavior to expect completion, then shift to partial acceptance via a /PROGRESS setting is good. You do not have to use multi-return syntax if you do not want, and can just pass a variable to it (as you would in R3-Alpha's DO/NEXT). It is near-certain that this is the actual endgame for multi-returns...to only be syntax sugar for what you could do with an ordinary refinement.

Refinements being their own arguments is a change I think you can't-not-like. The benefits to the model and code are tremendous.

Issues regarding things like TO or MAKE conversions, e.g. from WORD! to PATH! and back, need to be gotten right. We can hammer this out whenever you're ready, and the right answer shouldn't be hard to patch in.

You have the floor for voicing opinions and tuning the design, now. The last couple of days here I'm showing just how adaptive the conventions can be--that the changes can be made about as quickly as they can be articulated. Making a shim to change things backwards is nearly always going to be easier than the changes forwards, so hopefully you can have confidence in that.

We need the executables today-ish...including new mac binaries. So it's a now thing. They don't have to be exactly right...and you'll be the shot caller on how they are patched.

In general, I'm on board with this.

The biggest distinctions (off the top of my head) for me are: original slate of datatypes, conventional semantics for core functions (NULL/VOID change notwithstanding), the previous PARSE positional return (I feel this is the right call even for a conservative branch). The one deviation I'm open to is generalised quoting, but I'd like to explore the direction I'd suggested re. reflection.

I try not to set targets I can't keep, but I intend this week to go through the current R3C test suite in order to constitute a spec for that branch. Once done, hopefully that will be stable going forward.