-
Notifications
You must be signed in to change notification settings - Fork 4
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
A peculiar and fun Forth like compiler targeting bash functions, recently made available. #110
Comments
This is amusing to me because just yesterday I was thinking how funny it would be to implement Forth in BASH. There is no way I would have done it though. |
Here's another Forth in bash, but this one is virtual machine based, and therefore a tad slow: |
About 30 years ago I wrote Forth in PostScript in one page of code. |
At a point I attempted to code a Forth in Brainfck :) I got to the point of working random memory access, then I gave up on the attempt. That was about the time when I then switched to a Perl implementation, going the lazy route :) |
I was mentoring a high school student a few years ago and gave him a quick lesson in Forth. A couple of weeks later he came to me with an implementation in Haskell. He was having trouble with implementing data space but we figured out a way to do it by forking the workspace on every store operation. Hideously inefficient, but hey. |
mentioning Haskell, I was wondering what the most unlikely language used to implement Forth in was, thinking of a handful of code golfing languages like Jelly, Vyxal, and also Husk which took some inspiration from Haskell. My personal favourite may be a Forth running on a set of pneumatic or hydraulic valves as host CPU. |
This is great! Definitely one of the most unusual Forth implementations I've come across. |
Here is another implementation challenge; Minecraft Redstones.
Cheers
Niclas
…On 2022-01-09 03:47, Cat Stevens wrote:
This is great! Definitely one of the most unusual Forth
implementations I've come across.
--
Reply to this email directly, view it on GitHub [1], or unsubscribe
[2].
Triage notifications on the go with GitHub Mobile for iOS [3] or
Android [4].
You are receiving this because you are subscribed to this
thread.Message ID:
***@***.***>
Links:
------
[1]
#110 (comment)
[2]
https://github.com/notifications/unsubscribe-auth/AAA2BROKBXALVES4Y6DGWCLUVDZLFANCNFSM5LP5BV3A
[3]
https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675
[4]
https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub
|
I got the wiki running and a handful of pages populated, aiding with the description effort of everything related to yoda |
@Bushmills, I have looked at the differences, and I wonder why not use just another name when a word behaves differently? For example, you could rename your variants:
|
@ruv, thank you for your thoughts on standards compliance. This is valuable and very much appreciated input! |
Just another quick additon on the |
I too am a big fan of changing the name if the detailed semantics change. Otherwise anyone else trying to read the code can become utterly confused. And if you do decide to try and implement the standard version, you can do so without having to rewrite old code that uses the variant. My mantra: Names Are Cheap |
Valid points you have there, @MitchBradley. You guys make so much sense here. |
I've followed your valuable suggestions re word naming, and made |
I am glad that the suggestions made sense to you. It can be difficult to come up with good new names, but reusing an old name that has an established meaning usually causes problems going forward. |
As my use of yoda is in parts also as experimentation vehicle, here's one of the observations gained from it, which may be worthy of consideration in other Forths and Forth-alikes: delayed headers creation. These do away with the commonly implemented hide/reveal construct, rendering it unnecessary and removing yet another header flag (if implementation of hide/reveal uses those). Therefore has delayed headers creation the potential to complement replacement of precedence header flag. What I'm doing for delaying headers creation is to leave it to semicolon to create the headers of colon words. Should compilation fail, no header will be created at all. Should a header by the same name be referenced during compilation, as it happens when compiling the former version of a word into a redefinition of it, the new header isn't found because it hasn't been created yet. |
On 07/02/2022 at 10:24 AM, "Bushmills" ***@***.***> wrote:
As my use of yoda is in parts also as experimentation vehicle,
here's one of the observations gained from it, which may be worthy
of consideration in other Forths and Forth-alikes: delayed headers
creation. These do away with the commonly implemented hide/reveal
construct, rendering it unnecessary and removing yet another
header flag (if implementation of hide/reveal uses those).
Therefore has delayed headers creation the potential to complement
replacement of precedence header flag.
What I'm doing for delaying headers creation is to leave it to
semicolon to create the headers of colon words. Should compilation
fail, no header will be created at all. Should a header by the
same name be referenced during compilation, as it happens when
compiling the former version of a word into a redefinition of it,
the new header isn't found because it hasn't been created yet.
Reason for delaying headers in yoda is actually a different one,
so the effects on avoiding self-referencing during compilation are
more a side effect, a byproduct, but one of a kind I consider
valuable enough to think of utilising such an approach for this
goal alone already: get rid of hide/reveal.
There was a fig-version called Split-Forth where the headers were
kept very separate from the code. The idea was that the headers
could be eliminated when the application was complete. Sounds
like you are aiming at something similar.
Regards
Paul E. Bennett IEng MIET
Systems Engineer
Lunar Mission One Ambassador
--
********************************************************************
Paul E. Bennett IEng MIET.....
Forth based HIDECS Consultancy.............
Mob: +44 (0)7811-639972
Going Forth Safely ..... EBA. www.electric-boat-association.org.uk..
********************************************************************
|
Hi Paul, |
yoda is a spin-off of another experimentation platform, which was mostly used for testing ways to do constant expression folding, which is why words weren't compiled incrementally, but code - and pseudo-code - was buffered for post-processing, triggered by semicolon. yoda inherited this postprocessing, but not the CEF optimisation. With this already in place, delegation of header creation to this post-processing phase was then only a small step. |
I usually do it as well, using the following words:
(where I want to find better names for these words (especially for latter one). |
@ruv, what are your experiences with this approach of reversing the order of compilation and header creation? Any problem points you have encountered as far? |
Actually, a standard system may have different degrees of compliance (see 5.1.1 System compliance). And it's easy to make a system compliant: it's enough to provide the Core word set only (see 3 Usage requirements). Concerning other standard words, a word should be either provided and compliant, or not provided. Character strings
It looks like Forth in Bash is not about efficient at all ;) Standard character strings can be provided for compatibility only. A Forth system may use any other representation of strings for its internal use and/or in additional APIs. |
"It looks like Forth in Bash is not about efficient at all ;)" - The more the reason to not substantially slow it down even more if it can be avoided - it may just make the difference between "usable" and "unusable" |
Usually the lifetime of a parsed string continues until the next refill, and in such a case you need to save the string containing the name of a word somewhere up to ending compilation of the word. As an option, a header can be created at once, but appending into the compilation word list can be delayed. There is no such a problem if a parsed string lifetime continues until the whole file is translated (as it was in one my case).
Then probably the line number should be taken just before start compilation of the definition. I would associate this line number with xt to provide this information for anonymous definitions too.
See a full example in my gist. It also shows one way how to deal with the name and create the header after end of compilation of the definition. |
It's OK. All these artifacts are implementation details that are under the hood. The standard is a quite high-level abstraction that hides all such details.
An execution token is not an address. It's an unspecified cell that only identifies execution semantics, and nothing more (see also Data types).
As we can see, Tick (
What is missed is the
Now
BTW, even the core
|
Almost ... but, this wouldn't have worked as you wrote it in versions which postpone headers. It seems that you're basing this on a version of yoda from before header creation was postponed. |
I relied on Actually, When you provide A proper implementation (and handling) of |
yoda supports forward references. for compile, and postpone, the call to a function can be compiled while the function doesn't exist yet. When defined later, the name of the compiled but declared "still missing" function will be used for naming the resolved word. |
It nothing to do with the problem I'm talking about. Take a look:
in these both lines I append something to the current definition when it's effectively absent. Concerning forward references. It seems this conception is applicable to ordinary words only. And then a system should throw an exception if the word that was forward referenced, later is defined as not ordinary (e.g. if it's compileonly). |
I admit that I don't quite understand. First line you may be referring to Here I've added stub/pretend lit, and compile, to library, source at bottom of screenshot. (ed: I was tempted to let tick resolve from library, but decided against it because I use tick too often to check whether a word is present - in those cases I don't want the system to take action towards causing them to become present. That'd be like quantum resolving - the test affecting its own result) |
Sorry, I meant the words defined in a preceding message:
Well, even without any additional definitions, my point can be illustrated by system-specific code:
|
I see now. Your assumption that those compile anything is possibly why I didn't understand: |
This, btw, is also the reason why implementing headerless words is no triviality in yoda, and why I for now settled for a dummy header which gets discarded instead: Same thing applies (for a simple "real" headerless solution): without taking some specific actions will the headerless code simply vanish. |
No. My assumption that such compilation is incorrect and a Forth system may throw an exception on that. And then a question is how to implement that the system throws an exception when a program tries to compile anything when the current definition is absent. (And in the comment above I mentioned that Using the word
The word
Yes, but it will be a delayed exception: not when an incorrect operation occurs, but when a correct operation occurs after an incorrect one.
Yes, in this case it's better to ignore the error than report it delayed.
A Forth definition can be named or nameless (anonymous). Whether it has any header or not — is hidden under the hood; the standard doesn't specify any headers at all. So I don't see what makes not trivial for yoda to support nameless definitions (i.e. to implement the |
It seems that standard doesn't require |
Yes. Such a word is not standardized yet. Some proposals were discussed in comp.lang.forth though. My point was that xt of the most recently created word, and xt of the current definition (i.e. that is under construction) should not be mixed.
There is no such a way for a named definition. For an anonymous definition, which is defined via For example,
Concerning etymology,
See my gist for description, rationale, and an implementation example. |
After some musing I now arrived at this position:
|
Revisiting the matter of single vs double length numbers with pictured number conversion words |
They are not compliant because they produce a different result. Is "+" compliant if Either implement the standard or do not. |
It's very unexpected, error-prone and frustrating for a user. If you don't want to handle the most significant part, then, if this part is nonzero, throw an exception with a clear error message, but don't silently ignore it. Also, document it as an environmental restriction. Also take into account that If performance is a bottleneck, I would use an alternative set of words for single numbers pictured-numeric output (e.g. |
My various Forth systems have used u#, u#s, and u#> for single numbers since the dawn of ANS Forth. The standard double-number variants are, of course, fully supported. |
Excellent naming. I like it! And the word |
Fully functional pictured number conversion words working on double length numbers in combination with single length number outputting words still using the words for single length pictured number conversion, after which the headers (and in parts, their code, when inlined) of those words were removed sounds like the best deal, which is why I went this path now. Given that those headers are trashed anyway after use, the naming wasn't really that relevant - i went for |
What do you suggest I should do with |
The word OTOH, you can define
Just choose some appropriate value for |
Indeed, that's an effective way to solve it. My mind was somehow set to providing "real" data, ignoring that an arbitrarily designated value is just as real. |
As I like Forth to be fun too, apart from its practical aspects, I've been enjoying Forth written in lesser likely languages, from scripting languages to editor macros to mobile device "automation" apps.
Here's my recent concoction, named yoda which is now at the point of starting to even become somewhat useful, with the gravest flaws and problems now eliminated.
It's a Forth-like implementation not based on a virtual machine, but compiling to bash functions. These compiled functions execute in the same context as the compiler responsible for generating them, which means that the compiler won't compile to a file which is then loaded and executed, but to the environment wherein it is running itself, very much like you're familiar with from about any Forth interpreter.
It features reasonable code transparency, by providing the words to access and view the source compiled words have been compiled from, as well as the generated code. It also features built-in word description lookup capabilities, aiming to lower the threshold to fledgling Forth users.
But in fact I shouldn't call this a "Forth", as it's merely "Forth like", as I didn't bother about trying to adhere accurately to one or several of the available standards, which is partly due to the host platform (bash) making it somewhat hard. Example: double cell integers, no "real" memory access, code space separated from (virtual) memory space, a return stack which doesn't live up to its name. However, it's up there for inspecting, toying with it and hopefully enjoying it.
About half of the words it provides has by now been described ("documented", sort of)
Requirements:
a computer running bash (that means, probably some Unixoid system), which has coreutils
and sedinstalled.Additionally, a text editor would be nice too. (sed dependency has been dropped)
The text was updated successfully, but these errors were encountered: