
Jonesforth – A sometimes minimal FORTH compiler and tutorial (2007) - jcla1
https://github.com/nornagon/jonesforth/blob/master/jonesforth.S
======
rwmj
2007 actually. Anyway, ask me anything!

The project comes in two parts. The first part is linked above. The second
part is written in FORTH -- or rather, a subset of FORTH initially that builds
up and adds features as it goes along:
[https://github.com/nornagon/jonesforth/blob/master/jonesfort...](https://github.com/nornagon/jonesforth/blob/master/jonesforth.f)
Try scrolling down the file, and notice how the comment syntax changes from \
(backslash) to (...) (parentheses), then notice that parenthesis-comments are
implemented just before the style change. There's a lot more stuff like that,
although that's the most noticeable thing for beginners.

~~~
listic
> Now some easy FORTH primitives. These are written in assembly for speed.

To think again, shouldn't a modern C/C++ compiler be able to produce better
code than this assembly without the intrinsic unportability? Let's take, e.g.
SWAP

    
    
        defcode "SWAP",4,,SWAP
        pop %eax		// swap top two elements on stack
        pop %ebx
        push %eax
        push %ebx
        NEXT
    

(and NEXT is)

    
    
        /* NEXT macro. */
        .macro NEXT
        lodsl
        jmp *(%eax)
        .endm
    

This won't really be blazing fast, or will it?

~~~
rwmj
The NEXT macro and terrible use of the stack is kind of integral to threaded
code. I'll let you read the tutorial to find out why :-)

In general you shouldn't expect FORTH to be fast -- it uses the stack far too
much and the way it does branching kills branch prediction on modern CPUs.

However it is very small and a lot of fun to write. If you are looking for a
system that can run on baremetal and where you can _completely_ understand the
system from top to bottom, then that's FORTH for you.

Compared to C, FORTH has an extensible syntax and features like exceptions.
Compared to FORTH, C is a lot easier to write significant programs in.

~~~
listic
I am nodding along, but we can't say we write in assembly for speed, if we
don't achieve much of it, can we? Especially if portable C turns out to not
actually be slower.

~~~
rwmj
Yeah I'm not going to defend FORTH as a practical language -- it's annoying to
write significant programs in it. However it does fit in a smaller space than
C (probably).

I'm currently writing an ML derivative language for smaller systems and I hope
that'll be practical while at the same time being a better alternative to C.

~~~
sitkack
Have you looked at ATS? [http://www.ats-lang.org/](http://www.ats-lang.org/)

~~~
rwmj
Not until now. I was writing a language because it's fun, not because it's
intended to be useful though.

------
PaulHoule
Back in the 1980's I had a TRS-80 color computer which was running a Unix-
clone operating system called OS-9, this was multi-tasking and multi-user so I
could log into my Coco with a DEC Correspondent printing terminal.

I wrote a FORTH implementation for the 6809 in about 3k lines of assembly code
which included the language plus the 'standard library'. Instead of the
'standard' Forth I/O, there was an interface to Unix-style file-handle based
I/O. It used subroutine threading so that FORTH compiled directly to 6809 code
and the part that did dynamic dispatch used self-modifying code to shave off a
few cycles.

FORTH is an interesting part of the story about why LISP didn't take off on
1980's microcomputers, partly because if you wanted a LISP on an 8-bit micro,
you could get much of the way there with FORTH in a footprint even smaller
than BASIC.

------
ruda
This is [https://github.com/ruda/jonesforth-
macintel](https://github.com/ruda/jonesforth-macintel) the port I did to
Macintosh i386.

------
Someone
Read it once more, and it was a good way to remind me of how fun programming
was before we had megabyte libraries and dozens of layers of abstraction.

I also noticed something that made me smile:

 _" There is no generally agreed syntax for this, so I've gone for the syntax
mandated by the ISO standard"_

You won't read that in the source code of a C, pascal, or Fortran compiler,
and there basically is only one forth standard, but historically, many
implementations know better than to follow it. That is both a good and a bad
thing.

On the plus side, it is extremely flexible, but the price one pays for that is
that there is barely any code reuse because every system is different.

For systems on which Forth shines, that isn't a problem. There, you do not
include that 400 byte floating point library "as is", but take the source,
remove the 2% of it that you do not need, and tweak a few calls to make them
smaller at the price of performance because you don't have 400 bytes to waste
on a bloated floating point package. You don't _program in_ Forth, you _write
a_ forth.

------
paulsmith
How hard would it be to port this to x86_64? Offhand I'm guessing the
alignment, register names (eXX -> rXX), changing any relative offset from 4 to
8, and syscall convention. Any other hidden landmines?

~~~
rwmj
Kind of a bunch of work, but at the same time it'd be an interesting learning
exercise. There have been ports to quite different architectures, such as PPC
and ARM, and one you can run on baremetal RPi:

[http://www.lshift.net/blog/2007/10/04/jonesforth-ported-
to-p...](http://www.lshift.net/blog/2007/10/04/jonesforth-ported-to-powerpc-
and-mac-os-x/) [https://github.com/M2IHP13-admin/JonesForth-
arm](https://github.com/M2IHP13-admin/JonesForth-arm)
[https://github.com/phf/forth](https://github.com/phf/forth)
[https://github.com/organix/pijFORTHos](https://github.com/organix/pijFORTHos)

