the system exists, and it is working, but not public yet. i simply couldn't keep it to myself anymore. ;-)
so, in the good old tradition of making posts about projects i'll never finish, here is yet another one!
F8 Forth cross-compiler, featuring Succubus, native Z80 code writer
F8 is FAST cross-compiler for Forth language. instead of using an interpreter, as most Forth systems do, F8 generates native machine code, and inlines a lot of primitives on its way. my usual Erathostenes benchmark is ~8 times faster than with Abersoft Forth Recompiled (which is DTC, and already faster than the original Abersoft Forth).
to give you some numbers: Abersoft Recompiled takes about 9 seconds (slighly less) to finish the benchmark, and F8 is able to do it in ~800 msecs.
of course, for real programs the results will not be such impressive, but i still expect x2-x5 speedup for most Forth code.
yet everything has its price: the code generated by F8 is bigger than the usual Forth threaded code. and you won't have an interactive interpreter to play with. but F8 is able to trace your program, and include only words it used. i.e. you tell F8 what the "main" word is, and F8 includes only the code which was really used, throwing away everything else. it also throws away all word headers. so most of the time, F8 will be able to produce both smaller and faster programs.
i wrote F8 because i am planning to use it for writing my own software, so it's not Yet Another Toy Project. also, F8 comes with a freebe: native x86 Forth compiler for GNU/Linux (because this is the language F8 written in).
(ok, i must confess that it was started as R&D project for Succubus/Z80, and it is still highly experimental. but it works, and works even better than i expected.)
both compilers featuring Succubus — optimising native code writer. for x86, Succubus is able to generate machine code comparable with SPF4, and she prolly even able to beat some commercial Forth compilers. most of the time,
x86 code generated by Succubus is ~2 times slower than "gcc -O2". and she is able to do that in milliseconds! rebuilding the whole x86 system takes ~60 msecs, and this is more than 500 KB of Forth code!
when Succubus writing code for Z80, she is lightning fast too. even for huge Forth programs you will prolly not be able to notice the compiling itself. your Speccy emulator might start slower than Succubus finishing her job! ;-)
so you'll be able to instantly test your Forth code, almost like if you have an interactive interpreter!
F8 can generate standard .tap files, +3DOS .dsk images, and .sna snapshots. it doesn't support 128K, though. that is, the code will work, but there are no special tools to use additional 128K memory. but you have built-in Z80 assembler available, so you'll be able to write your own memory managing system.
see also: M4Forth
you may also take a look at M4Forth.
this is another Forth cross-compiler, written in M4 macro language. it has similar goals, but completely different implementation. it's great, and you will not want to miss it if you are interested in Forth! besides, this is the only Forth compiler written in M4 (at least i haven't seen others ;-).
F8 vs M4Forth
while both compilers generate native Z80 machine code, there are two major differences.
first, F8 is doing aggressive inlining, which is quite important if you are writing real Forth code (with many small words) instead of "C with awkward syntax and manual stack manipulations". of course, M4Forth can be improved to perform inlining too, so... this one is not that major. ;-)
second, F8 is FAST. M4Forth compiling speed is limited by M4 implementation, and it could take several seconds to compile your code. F8 is able to do everything in less than half of a second; i don't think that you will be able to make it spend more than 300-600 msecs even on most complex source code.
yet, the code generated by M4Forth is usually better and faster. if it will get inliner (or you will write the inliner yourself), M4Forth may be better than F8 if you need to squeeze more tstates from our beloved Z80.
also, M4Forth is mostly compatible with Forth standards, and F8 is totally non-standard. it doesn't even have your usual "IF/BEGIN" words! (don't worry, conditions and loops are there, they just slightly non-conventional.)
code generation: sample
source:
Code: Select all
$9000 zx-constant flags
8192 zx-constant size
zx: do-prime ( -- count )
flags size -1 fill
0 0 << ( count index )
dup flags + c@
?< dup 2* 3 + 2dup +
<< dup size - -?^| dup flags + 0 swap c! over + |? else| 2drop >>
swap 1+ swap
>?
1+ dup size - -?^||
else| drop >> ;
Code: Select all
8016: E3 ex (sp), hl
8017: 22 62 80 ld $8062 (), hl
801A: 21 00 90 ld hl, # $9000
801D: 11 01 90 ld de, # $9001
8020: 01 FF 1F ld bc, # $1FFF
8023: 71 ld (hl), c
8024: ED B0 ldir
8026: C5 push bc
8027: 69 60 ld hl, bc
8029: 5D 54 ld de, hl
802B: 3E 90 ld a, # $90
802D: 84 add a, h
802E: 67 ld h, a
802F: 7E ld a, (hl)
8030: B7 or a
8031: EB ex de, hl
8032: CA 59 80 jp z, # $8059
8035: 5D 54 ld de, hl
8037: 29 add hl, hl
8038: 23 inc hl
8039: 23 inc hl
803A: 23 inc hl
803B: 4D 44 ld bc, hl
803D: 19 add hl, de
803E: D5 push de
803F: C5 push bc
8040: 7C ld a, h
8041: D6 20 sub # $20
8043: F2 54 80 jp p, # $8054
8046: 5D 54 ld de, hl
8048: 3E 90 ld a, # $90
804A: 84 add a, h
804B: 67 ld h, a
804C: 36 00 ld (hl), # $00
804E: E1 pop hl
804F: E5 push hl
8050: 19 add hl, de
8051: C3 40 80 jp # $8040
8054: E1 pop hl
8055: E1 pop hl
8056: D1 pop de
8057: 13 inc de
8058: D5 push de
8059: 23 inc hl
805A: 7C ld a, h
805B: D6 20 sub # $20
805D: FA 29 80 jp m, # $8029
8060: E1 pop hl
8061: C3 00 00 jp # $0000