[HN Gopher] Jonesforth - A sometimes minimal Forth compiler and ... ___________________________________________________________________ Jonesforth - A sometimes minimal Forth compiler and tutorial (2007) Author : Tomte Score : 84 points Date : 2022-05-13 14:36 UTC (8 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | [deleted] | mftb wrote: | What a cool thing and this thread also appears to be full of | gems. I'm on a Lisp journey for the next little while, but I'll | eventually get to Forth. Filing all this away for later... | codr7 wrote: | I would recommend going the other way as it will probably be | easier to appreciate both that way, just from my own experience | both learning and writing interpreters for both. | | Lisp is sort of the next step after Forth if you ask me, adding | slightly more syntax to get better abstractions. | samatman wrote: | I'm inclined to agree with you, just chiming in to say that | historically, Chuck Moore was a student of John McCarthy, so | Forth was one of many 'next steps' after Lisp. Which is a | very old language. | dmytrish wrote: | It was a lot of fun for me to reimplement this in MIPS assembler | on CI20 [0] | | JonesForth could be more clear about the high-level logic of its | interpreter part. I tried to make this part as clean as possible, | hopefully did not miss anything. | | Maybe I will make a RISCV version in my _copious free time_ in | the future. | | [0] https://github.com/EarlGray/language- | incubator/blob/29755c32... | drivers99 wrote: | I want to write one for bare metal (non-Linux) raspberry pi | (ARMv6 32 bit on Raspberry Pi 1 and Zero; ARMv7 and ARMv8 on | higher models and also supports 64 bit). I want to have no | dependencies required though so was thinking of bootstrapping | it with nothing but machine code (determined initially with the | help of an assembler and documentation of course). Someone has | already ported jonesforth the Raspberry Pi[1] but using serial | i/o as the user interface and it has dependecies to build it, | but I should be able to get ideas from how they coded their | assembly parts compared to the original jonesforth. I want to | be able to use HDMI for the screen (already tried it out with | some bare metal tutorials in assembly so that's do-able) and | again, with no dependencies. And I want to show people how to | do it themselves, not just have it be something to run that | they don't understand fully. It should also be possible to have | the forth kernel build/assemble itself if needed, or cross- | target another platform. | | I know I'm all talk right now, like you say, I need to manage | my free time so that I would have the "copious free time" to | work on this. | | The only reason I was thinking Raspberry Pi was I wanted | something that would be readily available to anyone (although, | at the moment it's out of stock due to supply chain issues). I | was actually looking at whether anything similar was available | with RISC-V (like you mentioned) to target, since that would be | interesting. | | [1] https://github.com/organix/pijFORTHos | bowsamic wrote: | The only thing anyone ever seems to do with forths is write | another forth. Why is this? | | Unrelatedly (perhaps) I tried writing some basic software in | forth and it was pretty horrific. Even something as simple as | representing a variable length array feels like fighting the | language | adastra22 wrote: | It is the community that surrounds forth, and the type of | hobbyists that are attracted to forth, as well as what they are | attracted to. | | It's a bit like saying the only thing anyone ever seems to do | with Common Lisp is to make macros which redefine the syntax of | language. How frustrating! We'll if they didn't want to make | use of macros, why were they using lisp in the first place? | | Part of the appeal of forth is making your own forth | environment. That is the whole answer I think. | orthoxerox wrote: | Because forth is an exercise in minimalism, its answer to most | features is YAGNI. The coolest thing about it is how easy | something as weird as forth maps to the quite different | different underlying (register-based) hardware, so you can use | a forth to bootstrap something with more sugar. | Gordonjcp wrote: | Possibly a variable-length array wasn't a good fit for the | problem you were trying to solve. | zozbot234 wrote: | > Unrelatedly (perhaps) I tried writing some basic software in | forth and it was pretty horrific. | | It might be instructive to compare FORTH to e.g. the previously | discussed language K, which is similarly terse in some ways. It | turns out that a few convenience features - including first- | class- and higher-order- functions, neither of which really sit | well within the FORTH stack-focused model - can make a real | difference. | fmakunbound wrote: | If you've seen one Forth, you've seen one Forth. | nikolay wrote: | It's strange that Lisp became so popular, and Forth - not so | much! I've enjoyed GraFORTH on Apple ][ and then using it to | generate it in PostScript to generate logos and complex graphics | programmatically not using an editor. | codr7 wrote: | Forth is a great place to start, I've done several remixes in | different languages along the way: | | https://github.com/codr7/fibr | | https://github.com/codr7/forthy2 | | https://github.com/codr7/gfoo | | https://github.com/codr7/fipl | haolez wrote: | When I see FORTH stuff like this, I cannot avoid thinking that in | a post apocalyptic world, we would be scavenging computer parts | and writing FORTHs to use them :) | mncharity wrote: | For a different apocalypse poem, allow everything existing to | be used, but the coming population collapse demands a full | stack replacement. To preserve existing capabilities and | progress, but supported by far fewer people. | | We've had environments with far greater individual programmer | productivity than is currently common. But while forth starts | out nicely with simple systems, costs escalate unhappily with | goal complexity. Similarly with smalltalk, lispms, prolog, | haskell. The perennial "we'll easily do a full-stack rewrite in | our wonderful X" efforts... haven't. | | Past/current efforts avoid implausible goals, like LLVM-quality | compilation has to become a one-person project. Or slather on | viability constraints, like must run on M in time T, and be | accessible to population P. Or "we don't know how to compile | that leverage efficiently and consistently - that paper hasn't | been written yet - so you can't have it". | | But there are increasingly opportunities to do things | differently now, if narrower goals demanded it. Community-wide | compilation caches - "it ok that the type proof / bulk code | translation / whatever sometimes takes days, it only needs to | happen once". Compiler runs spinning up 10000 cloud instances. | And so on. | | What might it look like, to attempt not merely a bootstrap, but | a subsuming breakaway? | eternityforest wrote: | I think the current system would be supportable with a | collapse. You have fewer developers... but also fewer | hackers, so I would guess security stays the same, other than | if the collapse created extra crime incentive. | | We could just freeze all the fundamentals. If it was a real | emergency, we could mostly stop working on new niche | languages,Stop adding language features, stop deprecating | stuff, and just focus on essential applications with only the | tech we have. | | We'd obviously want some level or new work on the | fundamentals and language level stuff, but we'd just focus on | things that help you code with less people and poorly trained | people(Replacing C with Rust could be the big project of the | century). | | Tech is pretty great at the moment, seems like we could just | get by for centuries, totally long enough to rebuild, if we | just had what we have now, and enough hardware infrastructure | to keep the fabs running. We don't really need a new kernel | or a new graphics card architecture until society is stable | again. | 7373737373 wrote: | See https://bootstrapping.miraheze.org/wiki/Main_Page | | > This wiki is about bootstrapping, i.e., building up compilers | and interpreters and tools from nothing. | carapace wrote: | I just used Jonesforth as a guide/model to write a Forth for | the Project Oberon RISC chip last week. It's not finished yet | but it works: | | https://git.sr.ht/~sforman/PythonOberon/tree/master/item/for... | | https://git.sr.ht/~sforman/PythonOberon/tree/master/item/for... | | The idea is to make something like (or a port of) CollapseOS, | but with a 32-bit machine. The Oberon RISC chip is big enough | to be more useful than 8-bit systems yet simple enough that you | could build one out of discreet components if you had to. It's | really _really_ simple. | stevekemp wrote: | On that theme, collapse-OS has a discussion: | | http://collapseos.org/forth.html | WalterGR wrote: | "Forth isn't particularly fast either. As an interpreted | language, it is blazing fast, but the speed tax of the | threaded model still has to be paid, so it will generally be | slower than code produced by a C compiler." | | Not being familiar with this sense of "thread," I found a | good explainer here: | https://www.complang.tuwien.ac.at/forth/threaded-code.html | | And, as always, Wikipedia: | https://en.m.wikipedia.org/wiki/Threaded_code | shadowofneptune wrote: | Theaded code always interests me, but there definitely is a | price to it. Should be noted though that a lot of newer | Forths diverge from the classic threaded code model. | Because it is a concatenative language, it is possible to | have one that compiles native code by copying inlined | subroutines (https://citeseerx.ist.psu.edu/viewdoc/download | ?doi=10.1.1.56...). | | For example to compile : SQUARE DUP + ; all the compiler | has to do is copy the machine code of DUP to the place | where SQUARE is being compiled, remove the ret instruction | at the end of it, and copy the machine code of + after it. | It can also do some small optimizations to remove redundant | instructions. | | You can do this with other languages, but concatenative | languages can make it as simple as literally concatenating | bits of code. | kragen wrote: | Yeah, that's pretty much how Ur-Scheme compiles, inspired | by bigForth: http://canonical.org/~kragen/sw/urscheme | j6a wrote: | kragen, I emailed you on the 28th, can you please check | it? | 0xdeadbeefbabe wrote: | It's like the compiler becomes the CPU you wanted in the | first place. | rwmj wrote: | There are a few issues here. Running threaded code | interacts badly with branch prediction. Essentially every | "word" (operation) is followed by a branch to the next | word, and those seem hard to predict (or at least with | 2010-era hardware they were very hard to predict, maybe | more modern branch prediction can do better?). The reason | is that a popular word, say, +/add, might be called from | all over the program. Only one copy of the word exists and | the indirect jump to the next word could go anywhere. | | However Forth does allow you to "inline" words, basically | form a new word by chaining together existing words, which | avoids this overhead. This doesn't optimise adjacent words, | but it still gets semi-reasonable performance. (Inlining in | JONESFORTH: https://github.com/nornagon/jonesforth/blob/d97 | a25bb0b06fb58...) | | Modern Forths just have regular optimising compilers so | none of this stuff applies, but they don't have the simple | purity of one that you write and fully understand yourself. | kaba0 wrote: | Just an anecdotal experience, but I'm currently writing a | JVM in Rust with a naive, interpreter loop. OpenJDK's | interpreter is a so-called template interpreter which | looks at the method's byte code and generates a given | machine code snippet for each instruction, puts them | serially next to each other and executes this buffer. The | advantage of the latter is that in the interpreter loop | model, one jumps back to the switch statement which will | jump to the next instruction's implementation, etc, while | OpenJDK's solution just continues execution serially, | taking advantage of the branch predictor. | | In my benchmarks that are definitely not suitable to | infer much, OpenJDK without JIT can perform 1.5-8x | better, though of course the whole implementation is | different so don't read too much into that. | cmrdporcupine wrote: | It's amazing to me in general how much of a divergence in | expectations of performance vs reality that branch | prediction misses causes in modern software. | | So many techniques that would improve performance on a | 1980s processor can be woefully inefficient on a 21st | century one. It's so easy to be still holding the | computing model of the former in your head. | kaba0 wrote: | What is absolutely crazy is that many "primitive | computation" is basically free. Like, there is more than | likely some memory stalls either way and they just happen | in the pauses not causing longer execution time. | retrac wrote: | As with all languages, the compiled/interpreted distinction | is a thing of convention/existing tools. Interpreted Forth | is small, and tolerable speed-wise for tiny systems. But | Forth can also be compiled directly to native machine code. | | Relatively easily, you can get rid of the interpreter | overhead by writing blocks of machine code that do each | Forth word's action, instead of bytecode to dispatch the | interpreter to each of those routines. Forth can be adapted | for that easily enough, and some Forths do support this on | a per-word basis, allowing you to pick how you want your | words compiled. | | Forth can also get the whole optimizing compiler treatment. | Some optimizing Forth compilers have been released, but I | don't know how good they were/are. Certainly never needed | that kind of speed myself. I don't know if any Forth yet | benefited from it, but a lot of work was put into Java, on | approaches for optimizing stack machine-style code to | reasonably fast native code for register machines. | siraben wrote: | Some time ago I wrote an implementation of Forth that runs on the | TI-84+ and TI-83+ calculators directly inspired by Jonesforth.[0] | It runs under TI-OS as well, but the amount of available space is | somewhat limited. On another implementation I wrote[1] you have | full access to the calculator hardware and memory from Forth. | | [0] https://github.com/siraben/ti84-forth | | [1] https://github.com/siraben/zkeme80 | stevekemp wrote: | Here's one of the many forks that brings it up to 64-bit: | | https://github.com/matematikaadit/jombloforth | | If you like forth there's an awesome series of comments here on | hacker news on building a simple variant in a few simple steps: | | https://news.ycombinator.com/item?id=13082825 | | I took that, and built a simple forth-like system, in golang | following the original recipe and breaking it down into simple | steps for learning-purposes: | | https://github.com/skx/foth | zevv wrote: | [SSP] Assembly is of course nice, but not always practical. For | those interested in a compact, embeddable and portable little | Forth written in C, take a peek at zForth: | https://github.com/zevv/zForth. ___________________________________________________________________ (page generated 2022-05-13 23:00 UTC)