Trace: » forth05.html

[hemmerling] FORTH 5/6

Implementation of your own FORTH System & Applications

FORTH - The Good, the Bad and the Ugly

The Good - Valuable OpenSource FORTHs

⇒ See FORTH 3/4.

The Bad - Commercial FORTH Systems

  1. No source code. Means you can´t learn about the implementation of FORTH words & libraries... for better understanding. The application developers are lost!
  2. Compatibility problems, and nobody takes care of it. The application developers are lost!

The Ugly - Toy FORTH

  1. Not beeing developed by
    1. Senior developers with professional skills in compiler design, embedded systems,.. with 5+y experience ( e.g. college / university professors, engineers with much professional industrial experience,... ).
    2. Senior “assembly language artists” :-) with 5+y of experience.
  2. Without free and immediate / fast / quick support on professional level.
  3. Without comprehensive paper / PDF / HTML,... documentation.
  4. Without comprensive comments in the source code.
  5. Without much sample code & sample projects.
  6. Which might be “not in active development anymore”.
  7. Where the developer gets angry if his / her FORTH is considered to be a “Toy FORTH” :-(.
  8. Do most of the 1000 FORTHs have “more than one user” ? Or is it typical, that either
    1. The FORTH has no killer-application at all ( the only developer develops for all the years just FORTH, not a software solution for a real given application / problem ),
    2. Or the only developer has ONE software / hardware application for which he/she is using the self-developed FORTH with his self-developed software application code on top of the bare FORTH implementation?

Valuable FORTH vs. Toy FORTH

  • User experience and feedback: “If you have a good FORTH it is great fun to talk to the computer. Otherwise it is also torture :-(”.
  • User opinions:
    • “You can't write your own FORTH as rookie in compiler design & assembly language coding. That's all stupid what these 'Toy FORTH' developers tell you, that they can do it. Of course you can write a FORTH of 35 words yourself, but what's the benefit?”.
    • “Maybe there are '10000 FORTHs' on GitHub, but as you can see I can't name more than 10 that are really useful. So for me there are 9990 Toy FORTHs ... :-)”.
      • User #1 opinion: “99 % of all Forths I know are simple Toys , this means unfinished proyects. They implement the basic VMachine and then basta. They do not offer a simple Editor embedded in their Forths (as it was in the past a no question theme) they do not offer an Assembler or Disassembler :-(. Old style Forths as the ones I used to learn from in the past, had all those tools and much more. They offered Multitasking right from the start, vocabularies, block-file or os-file interfaces, direct video access, etc etc etc...:-)”.
      • User #2 opinion: “Forth has @ and !. You've missed the OP's point; it's the underlying architecture (for instance, Java and the JVM) that lacks direct memory access through pointers. That makes it hard implementing Forth on these types of systems”.
      • User #3 opinion: “Java has ByteBuffers, which can either be based on a Java byte array or on a directly-mapped file. That's everything a Forth needs”... “But I thought the JVM was sandboxed?”, “It is. ByteBuffers can only reach into the memory allocated for that buffer, but that's all that a Forth implementation needs. You could put the entire dictionary into a ByteBuffer. That'd be nice from the point of view of saving a precompiled image”.

Write your own FORTH Compiler

Slogan "Roll your own programming language - Roll your own Forth"

  • Inspired by the articles in Dr. Dobb's Journal of Software Tools “Roll your own DOS extender” ( Volume 15, Number 10, October 1990 + Number 11, November, 1990 ) and “Roll your own object-oriented language” ( Volume 15, Number 11, November, 1990, and online articles like InfoWorld "Learn Linux by rolling your own distro", 2017, I imagined the slogan “Roll your own programming language - Roll your own Forth” :-).

Implementation Types

Threaded Code
Tethered FORTH
  • Interactivity it just done on the host. The tethered Forth is just the compiled code.
  • High-level languages ( C, Lua,.. ) might be involved, for rapid development.
Native FORTH with Threaded Code
  • 100% pure assembly language. No high-level language involved ( C, Lua,.. ). This is how FORTH started, in the mid-1970th, with the first implementations for 8-bit microprocessor boards.
Native tethered FORTH
SRT / NCI FORTH ( Subroutine threaded / native Code inlining FORTH )
  • SRT/NCI means “subroutine threaded / native code inlining”.
    • “Subroutine threaded” specifically means that the code overall consists of subroutine calls to other words written as native code.
    • “Native code inlining” means that smaller words that are called that are able to be inlined are incorporated into the body of code which calls it as native code, eliminating the need for subroutine calls in those cases.
  • Example: zeptoforth.
FORTH which may create Application Executables
  • Examples: “Win32Forth”, “calForth”.
  • Narkive Archive "comp.lang.forth", Thread "TTC v DTC" - “token-threaded code versus direct-threaded code”.
  • Suggested reading: “Moving Forth: a series on writing Forth kernels” #.
  • An expert told me:
    • “Basic forth is all real mode. Mixed code and data”.
    • “That's not the only way to do it though. I've started doing Forth in web assembly which is part of the JavaScript engine of all browsers. This is a protected memory model which means you can't execute data directly. In those cases your pointers are really just offsets into a table of primitive functions. Forth runs completely fine in this model”.
    1. “ALForth” ⇒ See Forth 4/6.
    2. “f2u” ⇒ See Forth 4/6.
    3. “My Vectrex has a 6809 and 1KiB of RAM. Vectrex Forth (aka CamelForth 6809 with extensions) uses 1/2 of the RAM for buffers, TIB, etc. and after the BIOS reserved RAM is avoided, there are 256 bytes dictionary space available. Given Vectrex Forth is cross compiled and the whole compile+send process takes 1-2 seconds, 256 bytes is plenty for ongoing development”.
    4. With very small systems, one is better off using a tethered Forth such as Mecrisp-Across (for programming the MSP430 with one of the TI Tiva boards, I don't remember which) rather than a hosted Forth, which will inevitably take up some space. Tethered Forths can operate in very small spaces yet provide interactivity, and thus provide the best of both worlds”.

The Input, Input Processing & Compile Process ( Experts told me so )

  • Delimiter - not just “SPACE”.
    • “Generally all white space is treated as a delimiter. You can write words that parse from the input stream so this can be changed. The parser is usually about skipping all whitespace before the word starts. It will then read in every non whitespace character. The parser usually also recognises \ as the start of a comment and skips to the end of the the line and starts reading from there”.
    • Comments as delimiters: “Not with the way they decided to add line comments but I don't think this was the original comment system of Forth but added in the 80s. The original comment was the ( word which is an immediate words (a macro) which reads the input stream until it encounters a ) character. These kinds of comments these days are restricted to stack effects diagrams but there is nothing special about them, they are just comments”.
  • Input parsing:
    • The parser processes a whole line of input, not character-by-character as the characters are sent: “The parser can work on the line after the return has been entered. There are some subtle alternative approaches but this way is the simplest”.
    • “The input stream will go into a buffer and you read each word and execute the word. If you encounter a special word : it will go into compile mode and the rules change, macros (immediate words) like ; will be executed immediately, other words will be compiled into the heap (compiled into a definition)”.
  • Word processing.
    • “The words are processed as a stream”.
  • Stack.
    • “The stack is only used for interpreting and also for calculating loops and branches”.
  • Heap Allocator.
    • The heap pointer (bump allocator) is where you can allot new data objects. It can also allocate new words”.
    • “I think you can learn the majority of this flow from this article which I think it's really good. It's about implementing a Forth using Python” ⇒ OpenBookProject, Chris Meyers and Fred Obermann "Python for Fun", Chapter "FORTH - A simple stack oriented language".
    • Execution of FORTH words immediately, before end of line is reached:
      • “Peter Jackaki does exactly this with his Forth. I am very interested in his approach which has many advantages over traditional Forth”.
      • “The main disadvantage of traditional Forth is that it has two modes: interpret mode and compile mode. This creates complications like no loops or branches on the command line. Peter Jackaki's TAQOZ forth ( = Tachyon Forth ) compiles everything as it comes in. He watches the return and executes the compiled code. This changes a few things about Forth but I think it makes things simpler”.

The minimal FORTH System "sectorforth"

Primitive Stack effects Description
@ ( addr – x ) Fetch memory contents at addr
! ( x addr – ) Store x at addr
sp@ ( – sp ) Get pointer to top of data stack
rp@ ( – rp ) Get pointer to top of return stack
0= ( x – flag ) -1 if top of stack is 0, 0 otherwise
+ ( x y – z ) Sum the two numbers at the top of the stack
nand ( x y – z ) NAND the two numbers at the top of the stack
exit ( r:addr – ) Pop return stack and resume execution at addr
key ( – x ) Read key stroke as ASCII character
emit ( x – ) Print low byte of x as an ASCII character
Variable Description
state 0: execute words; 1: compile word addresses to the dictionary
tib Terminal input buffer, where input is parsed from
>in Current parsing offset into terminal input buffer
here Pointer to next free position in the dictionary
latest Pointer to most recent dictionary entry
  • : and ; provided.
  • NO immediate, [, or ].
What can I do?
  • “hello, world” of course :-).
  • Variables.
  • Stack debugging (.s, etc. )

General Compiler Building Resources

FORTH System Building Resources

Some other minimal FORTH

Excursus: C Data Types

    • “The minimum size for char is 8 bits, the minimum size for short and int is 16 bits, for long it is 32 bits and long long must contain at least 64 bits”.
    • “long long - Specified since the C99 version of the standard”.
  • WATCOM-C datatypes:
    • INTEGER*4 ⇒ 32 bit.
    • COMPLEX*16 ⇒ REAL 64 bit, IMAGINARY 64 bit ⇒ 64 bit.

Excursus: Use of SQL Databases to store FORTH Words

Write your own FORTH Code - FORTH Code Style

Traditional FORTH

"!", "C!" ( of fig-FORTH ) versus "=" and "\=" ( of pre fig-FORTH )

  • "CoinOp FORTH" - “Coinop forth was developed in Atari coinop division ..., based on DECUS forth for the PDP-11.. Later, as Forth became popular and fig forth came out, we did a port of it to the 800 as well. A major visible difference is that fig forth uses the new operators for stores ( ! and C! ) rather than the original ( = and \= ) which DECUS, coinop, Colleen forth does”


  • Traditional FORTH = Stack-oriented, like with RPN language of HP pocket calculators.

Modern FORTH

1Kbyte Screens / Blocks

  • See FORTH 2/4 ⇒ “The FORTH 64×16 Screen Paradigma”.

Array Words

  • For 50 years, array words were not delivered with standard traditional FORTH implementations :-(.

Batch Processing

  • Batch processing example, output is “1 3 5 2 4 6”:
    vocabulary voc1
    vocabulary voc2
    : txt1 ." 1 " ;
    : txt2 ." 2 " ;
    : txt1 ." 3 " ;
    : txt2 ." 4 " ;
    : txt1 ." 5 " ;
    : txt2 ." 6 " ;
    voc1 txt1
    voc2 txt1
    forth txt1
    voc1 txt2
    voc2 txt2
    forth txt2 

Built-in Web Server

  1. Forth2020 will shipped with a little Web Server.
  2. Server written with RETRO FORTH.
    • The OpenSource FORTH ForthWorks by Charles Childers "RETRO" ( RETRO Forth ).
      • “A clean, elegant, and pragmatic dialect of Forth. It provides a simple alternative for those willing to make a break from legacy systems”.
      • “You can view the glossary via Gopher or HTTP. This is served off the latest documentation in the repository by a server written in RETRO”.

Code Quality

Deferred Words ( DEFER, IS )

Floating Point Arithmetics

  • Many traditional FORTH gurus insist that floating point arithmetics is not needed, as “no sensor provides floating point data”. Bullshit, if many microcontrollers of the 2000s/2010th are shipped with a floating point unit!

Functional Programming with FORTH?

Input / Output - CPU / OS specific Memory I/O & Port I/O Access

Standard FORTH Memory I/O
  • “C@” ( read a 8-bit value / byte / character from a location ).
  • “C!” ( write a 8-bit value / byte / character to a location ).
  • ”@” ( read a number / pointer, e.g. 16/32/64-bit on a 8&16/32/64-bit systems, from a location ).
  • ”!” ( write a number / pointer, e.g. 16/32/64-bit on a 8&16/32/64-bit systems, from a location ).
  • “L@” ( read a 32-bit / 64-bit value / long number / long word, e.g. 32-bit on a 8&16/32-bit systems, but 64-bit on a 64-bit system from a location ).
  • “L!” ( write a 32-bit / 64-bit value / long number / long word, e.g. 32-bit on a 8&16/32-bit systems, but 64-bit on a 64-bit system to a location ).
  • “D@” ( read a 32-bit value / double word from a location ).
  • “D!” ( write a 32-bit value / double word to a location ).
  • Infos:
  • “C@” ( 8-bit value / byte read access ).
  • “C!” ( 8-bit value / byte write access ).
  • ”@” = “L@” ( 32-bit value / number / pointer read access ).
  • ”!” = “L!” ( 32-bit value / number / pointer write access ).
  • Infos:
    • Forth2020 "Esp32forth" - “ESP32forth digital R/W from a reg. - “You can access any address on the memory space of the ESP32 with the words L@ ( to retrieve a value ) and L! ( to store a value )”.
Open Firmware provides "Register" Access Words meant to access Hardware Devices
  • “RB@”.
  • “RB!”.
Port I/O for Intel 80x86, 808x & Z80
  • “PC@” ( 808X, Z80 and 80×86 ).
  • “PC!” ( 808X, Z80 and 80×86 ).
  • “P@” ( 808X, Z80, 80×86, though 808X and Z80 have just 8-bit I/O address space ).
  • “P!” ( 808X, Z80, 80×86, though 808X and Z80 have just 8-bit I/O address space ).
  • “PL@” ( 80×86 only ).
  • “PL!” ( 80×86 only ).
  • Demo implementation:
    \G Read the 16 bit port x1.
    CODE P@ ( x1 -- x2 ) \ EXTRA "p-fetch"
    MOV DX, BX
    IN AX, DX
    MOV BX, AX
    \G Read the 8 bit port x.
    CODE PC@ ( x -- char ) \ EXTRA "p-c-fetch"
    MOV DX, BX
    IN AL, DX
    XOR AH, AH
    MOV BX, AX
    \G Write x1 to 16 bit port x2.
    CODE P! ( x1 x2 -- ) \ EXTRA "p-store"
    MOV DX, BX
    POP AX
    OUT DX, AX
    POP BX
    \G Write char to 8 bit port x.
    CODE PC! ( char x -- ) \ EXTRA "p-c-store"
    MOV DX, BX
    POP AX
    OUT DX, AL
    POP BX
  • Infos:
    • Usermanual Wiki "FT-86C and FT-86C/FP USER'S MANUAL" - “3.5 INTERRUPT CONTROL. The 8259A programmable interrupt controller is in local I/O space at Hex address 0008. It can be programmed using the P@ and P! commands in the same manner as the serial communications ports”.
    • Implemented by “CHForth”,...
  • “C@” ( 8-bit value / byte read access ).
  • “C!” ( 8-bit value / byte write access ).
  • “W@” ( 16-bit value / number / pointer read access ).
  • “W!” ( 16-bit value / number / pointer write access ).
  • ”@” ( 32-bit value / number / pointer read access ).
  • ”!” ( 32-bit value / number / pointer write access ).
Memory I/O for highly-optimizing FORTH Compilers to avoid Memory Access Optimisation
  • “P@”.
  • “P!”
  • “PC!”.
  • “PC@”.
  • “PW!”.
  • “PW@”.
  • “PL!”.
  • “PL@”.
  • Infos:
Port I/O, alternative Syntax
  • “IO@”.
  • “IO!”.
Jupiter Ace ( "FORTH Programming" Manual, Chapter 26 )
  • “IN”.
  • “OUT”.
Excursus: Intel 8086 Port I/O with MSDOS C Compilers


Loops ( DO ... LOOP )

Mocking for Top-Down Development

  • Mocking example:
    : I_dont_now_jet ;
    variable #I_dont_now_jet ' I_dont_now_jet #I_dont_now_jet !
    : bike #I_dont_now_jet @ execute ;
    : two_bike ." four weels " ;
    : one_bike ." two weels " ;
    : one ' one_bike #I_dont_now_jet ! ;
    : two ' two_bike #I_dont_now_jet ! ;
    one bike
    two bike
  • Mocking example #2:
    forth            \ use the vocabulary forth, use ORDER to see the vocabulary stack
    : bicycle ( -- ) \ make a word bicycle, ( -- ) that does not change number of items on the stack
    2 wheels !       \ store 2 in the variable wheels ,but gif a error becose it is not defind jet
    vehicle          \ call the word vehicle, but gif a error because it is not defind jet
    ; so bicycle is not made
  • Mocking example #3:
    variable wheels
    5 wheels !
    wheels @ .
    " it works
  • Mocking example #4:
    / "variable wheels" is a pointer
    variable wheels
    : vehicle cr ." my vhicle has " wheels @ . ." wheels " ;
    : bicycle 2 wheels ! vehicle ;

Provision of a Unit Test Framework

  • As support for the Test-Driven-Development approach ⇒ See FORTH 3/4.

Appropriate OpenDirectory Directory Pages

en/forth05.html.txt · Last modified: 2021/09/25 12:05 (external edit) · []
Recent changes RSS feed Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki