The Fate of Redbol Emulation In A Mostly Unbound World

100% Emulation of historical Rebol was always going to be impossible. But if we go forward with the model that most code is unbound, that's going to break even code that didn't do anything sophisticated with binding. Not only will any values you PICK out of a block or iterate over be unbound, but even basic quoting won't be bound:

e.g. this won't work:

rebol2>> thing: 10

rebol2>> foo: func [w [word!]] [return get w]

rebol2>> foo 'thing
== 10

I had a problem with this in emulating my very, very old whitespace interpreter. It quoted ADD and then put it in a block, expecting a DO of that block to run the ADD it meant.

Simulating Waves of Binding (Probably?) Impractical

You might think that so long as every word can still hold a binding, then historical behavior could be simulated by manually binding everything.

When a module loads, you could walk through it binding every word. Then when a function runs, you could copy its body and walk through it...overwriting those module bindings for functions and arguments.

But it would really mean rewriting everything. You'd have to redo MAKE OBJECT!, otherwise the indiscriminate binding would break its expectations--as it doesn't override explicit binding anymore.

Hooked Evaluator May Fix (Some) Cases

We already are going to need a hooked evaluator to handle things like PATH! looking up in objects (done presently with a hack to the main evaluator).

Another hook could just say that quoted things wound up bound under the same rules that non-quoted things use.

That would make this one whitespace example work, and maybe it would be able to run some more simple historical example scripts. But anything that mixes COMPOSE and DO is likely doomed.

This may just be the price of progress. Rebol2 emulation remains a good experiment of changing your baseline library, and it still would be a good example of that... for all the changes to primitives like FUNC and APPEND etc. It just may not be able to accommodate the different expectations of binding.

So on top of all the other complications, the situation just got a lot more... sticky

Big Alien Proposal 🛸 "/WORD" Runs Functions - #13 by hostilefork

The writing is on the wall:

Emulating Rebol2/Red is not important enough in the near term to make sacrifices that impede progress.

Redbol Was Not A Waste Of Time

From its modest start as a small script in 2018 to its more expansive emulation circa 2024, Redbol has informed and tested the design of Ren-C.

It legitimately ran historical scripts, even the complex %pdf-maker.r at one point. (Though later I focused the attention and CI handling on my own historical scripts, e.g. the original USCII and the original Whitespace Dialect)

But it required kludges in the evaluator--very ugly ones--to still support obj/subobj/accessor/refinement in a world where Ren-C required obj.subobj.accessor/refinement. The code handling that is a blight, and causes undue burden on switching this to obj.subobj/accessor:refinement while still handling the original form. What should be emergently elegant code following the new more coherent model would be torturous and correspondingly buggy.

Those kludges need to be cut out. And Redbol emulation will die.

What About Bootstrap?

The bootstrap executable doesn't have generalized TUPLE!. And it's not going to get it! :face_with_raised_eyebrow: That's simply too deep and far reaching a change to apply to sources circa 2018.

So you might think the kludges need to remain, since the bootstrap EXE will only ever understand obj/subobj/accessor/refinement... until the deep future where we're confident enough to bootstrap to a pure virtual binding EXE. Which would mean it needs to be not just robust, but faster too, otherwise my development will be slowed down. Realistically I would not schedule Pure Virtual Binding Bootstrap until at least 2026.

(If that seems like slow progress, it is not uncommon for much more rigorous projects with orders of magnitude more people to use "LTS" releases for their bootstrap.)

I Have A Plan! :scientist:

I'm just going to hack up the bootstrap executable's scanner.

ren-c-boot>> transcode "obj.subobj/accessor:refinement"
== [obj/subobj/accessor/refinement]

Then all the code that needs to run in both the bootstrap executable and the current executable can be written to the new style.

It's "trivial"cough to implement, it works, and it means the kludges for supporting all-path formats can be cut out of the modern executable.

But Redbol Will Be Dead...For Now :skull_and_crossbones:

Bringing it back to life and letting obj/subobj/accessor/refinement act in accordance with history will require parameterized evaluation. This would be kind of like how UPARSE lets you use a collection of COMBINATORs picked according to the type it encounters, you'd have EVALUATORs that did the same.

So Redbol would have in its evaluation map an entry for PATH!. It would map to something that would rewrite that path as the right sequence of PATH!/CHAIN!/TUPLE! (or perhaps just do the interpretation itself).

That PATH! evaluator would also have to notice when its first element was a CHAIN! that started with BLANK!. So :a/b would need to be rewritten as :a.b (or again, just directly evaluate...if these EVALUATORs are native code then so long as they've already done the analysis to know what a correct rewrite would be, they might as well just do the implied operations as they go).

The New Redbol Probably Won't Be Written By Me

I can imagine laying the foundations of parameterized evaluators, and using some Redbol behaviors as a demo. But I can't imagine myself feeling compelled to go deep into actually completing the whole emulation initiative.

So if it ever happens, it would be the pursuit of some enthusiasts (or enthusiast AI) who thinks it would be novel to run Rebol2 or Red code inside of Ren-C.

I don't think there are going to be any Rebol2 modules that will actually be relevant or useful in a practical sense to leverage in Ren-C. So it's only fun, nostalgia, and a tech demo.

We Can Still Leverage Tests (PARSE2, APPLY2...)

Being able to twist UPARSE so it acts like Rebol2 and Red was a great demo. And we can still demo it running Rebol2 or Red tests. It's just that anything that's not related to parsing needs to be updated.

; hypothetical Rebol2 COPY test in PARSE
(
    obj: make object! [what: <tag>]
    all [
        parse [{"} b <tag>] compose [text! copy result thru (obj/what)]
        result = [b <tag>]
    ]
)

We could keep things like that, and say parse: get $parse2 but just change the little bits that need changing:

(
    obj: {what: <tag>}
    all [
        parse [-{"}- b <tag>] compose [text! copy result thru (obj.what)]
        result = [b <tag>]
    ] 
)

So that's the way the tides are flowing at the moment. I'm sad to see Redbol get sidelined, but it's far outweighed by my positive feelings about the direction of the new designs.

It's a strange delicate balancing act with tons of spinning plates in the air to come up with strategies for these changes!

1 Like

I’m pretty confident saying that nobody will miss it

I’m not sure we are in the kind of secure world where we should encourage others to run old Rebol code in the library.

And that’s the main reason I can think of that someone would want emulation

I can only imagine. Time to let go of some ballast. :balloon:

1 Like

Of course it isn't trivial. :roll_eyes: But I made a bit of progress on it today.

One thing I forgot about is that PATH!s are used to represent filenames in some places. While they can't represent every possible filename, they can be used for tame ones... such as foo/bar/baz.txt ... and since Rebol source code files have tame names, PATH! is used in order to avoid needing the % prefix everywhere. Looks nicer in "file specification dialects".

(This "abuse" of PATH! instead of using FILE! was Carl's choice, originating from R3-Alpha. The desire to use this for filenames like 1-file.txt is an argument for the FUSED! proposal.)

But of course my "scan all dots as slashes" interferes with that. So I'm going to say that it stops turning dots into slashes once it sees an actual slash in the scan.

>> transcode "foo.baz.bar/mumble/frotz.txt"
== foo/baz/bar/mumble/frotz.txt

>> transcode "/foo/baz/bar/mumble/frotz.txt"
== foo/baz/bar/mumble/frotz.txt

That is compatible with what bootstrap should need.

Of course there's another thing the bootstrap executable can't/won't do, and that's make PATH!s with SET-WORD!s or SET-TUPLE!s at the tail. The modern executable will need these for antiform frame assignments. But simply skip the slash and do normal assignment.

 >> transcode "/foo: func [x] [print [x]]"
 == [foo: func [x] [print [x]]]

 >> transcode "/obj.accessor: func [x] [print [x]]"
 == [obj/accessor: func [x] [print [x]]"

I'm honestly looking forward to going through and wiping out the old all-path notation, introducing the tuples and colons in the bootstrap scripts. Sad, isn't it?

1 Like