[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)
 
web link (github.com)
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)