Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify bootstrapping #11

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open

Conversation

nickd4
Copy link

@nickd4 nickd4 commented Apr 25, 2022

This change attempts to simplify bootstrapping from gForth/SwiftForth, noting that I don't have SwiftForth and only test gForth.

With the original bootstrapping method, we were creating a very authentic preForth environment within the host Forth, by creating a new wordlist and then loading the entire preForth runtime system into it, except for a few essential "borrowed" words.

The files that controlled this process were load-i386-preForth.fs, load-preForth.fs and borrow.fs. Collectively they were quite complicated, and not being an experienced Forth programmer I didn't understand the details of borrowing in particular.

There was also another thing that I found confusing, which is the way that load-preForth.fs was defining pre and code so they skip their body. Initially I thought, shouldn't it be echoing the body to the output, instead of skipping it? But after a bit of thought I worked out the reason: Under an interpretive Forth system, you would expect a word like pre or code to be defined and then executed. But since preForth is only compiled, it's not possible to execute a word that was defined in the same run. Instead the words like pre and code have to be already defined and part of the compiler that is compiling the source. So this leads to the unusual pattern where pre and code are first executed, and then later on, compiled to use in next stage. And this indirectly explains why pre and code are being ignored in the initial bootstrap, as we are only compiling them. (!)

Thinking about it some more, I realized that the more elegant way of handling this situation is not to include the pre and code definitions in the initial bootstrap at all (rather than defining them to no-ops and then including them). Or in other words, we can use the primitives supplied by the host Forth instead of the asm primitives, in the bootstrap compile run. So we can omit the file preForth-i386-rts.pre from the bootstrap compile run. And the same logic applies to most of the high-level Forth code in preForth-rts.pre, it's already available in the host Forth with a few exceptions like case?, tab, *10 and stack strings.

Therefore, my new approach to bootstrapping is to split out the nonstandard words from preForth-rts.pre into preForth-rts-nonstandard.pre so that they can be used for the bootstrap compile run, whilst preForth-i386-rts.pre and preForth-rts.pre are omitted. I also have an extremely cut down version of borrow.fs / load-preForth.fs which I call preForth-bootstrap.fs. All this does is to deal with the tail call syntax which is nonstandard. So all of the nonstandard parts are now in either preForth-bootstrap.fs or preForth-rts-nonstandard.pre, with the former being not needed under pure preForth and the latter needed.

I also have an extremely cut down version of load-i386-preForth.fs which I call preForth-cold.fs and all this does is to call cold and then bye (mirroring what the main function does in compiled preForth asm code). The actual including of sources for the bootstrap compile run is now done from the gForth command line (I assume / hope this will also work for SwiftForth).

Thus the bootstrap compile command is now:

        cat \
preForth-i386-rts.pre \
preForth-rts-nonstandard.pre \
preForth-rts.pre \
preForth-i386-backend.pre \
preForth.pre \
|$(HOSTFORTH) \
preForth-bootstrap.fs \
preForth-rts-nonstandard.pre \
preForth-i386-backend.pre \
preForth.pre \
preForth-cold.fs \
>$@

Note that redefinition warnings are generated for some words like cold that have different meanings under the host Forth than the preForth compiler. I could suppress these, as was done in the original load-preForth.fs, but I thought it not necessary. If the initial bootstrap process is a bit ugly it does not really matter, as once bootstrapped you can use the preForth way instead.

Once again, the changeset will look larger than it really is, so please merge the previous PRs then have github recalculate it.

…to bss rather than text section which avoids the need to call mprotect(), rename things
… be wrapped with PROGRAM / END, also removes automatic bye token that was generated by END
…time.seedsource, so that we can run textual forth code without the tests or the banner
… writes to stderr, fix self-hosted tokenizer termination issue (was debugged with eemit)
…ng the nonstandard words on top of gForth's standard words, produces redefinition warnings
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants