This commit is contained in:
Miloslav Ciz 2024-08-19 21:04:41 +02:00
parent ac9725b356
commit 3a465aea74
21 changed files with 1985 additions and 1866 deletions

View file

@ -12,7 +12,7 @@ Forth is unique in its philosophy, we might almost go as far as calling Forth a
Being somewhat of a misfit in terms of classification, the language is probably more often presented as [interpreted](interpreter.md), but that's a tiny bit misleading (interpreting Forth is almost like native execution), however it may perfectly well be [compiled](compiler.md) to pure machine code too; it's actually very easy and natural to turn Forth source code into assembly, however (again, due to Forth's unique nature) it is not so easy to state with confidence whether the language is really interpreted or compiled because interpreting Forth happens on such a low level that it's almost native code execution -- any newly defined word is immediately compiled into a list of addresses of other words (i.e. in C terms function pointers) and the most basic words are typically written directly in [machine code](machine_code.md), so the interpreter doesn't perform any search for word names or anything like that (like a typical scripting language would), it just jumps between memory addresses, pushes numbers on stack and sometimes runs a native piece of code. For this Forth may be seen as a kind of "wrapper for assembly" as well, one that helps it be [portable](portability.md) (to port a program one will just have to replace the machine code of the basic words).
Forth systems traditionally include not just a compiler/interpreter but also an **interactive environment** in which one is defining and compiling new words on the go. Again -- this is not just some kind of extra killer feature, an interactive environment naturally comes as a byproduct of Forth's design, it costs nothing to have such environment. This environment can serve for example as a debugger or even an operating system.
Forth systems traditionally include not just a compiler/interpreter but also an **interactive environment** in which one is defining and compiling new words on the go (by this it's similar to [Lisps](lisp.md) that are usually interactive too). Again -- this is not just some kind of extra killer feature, an interactive environment naturally comes as a byproduct of Forth's design, it costs nothing to have such environment. This environment can serve for example as a debugger or even an operating system.
There are several Forth standards, most notably ANS Forth from 1994 (the document is [proprietary](proprietary.md), sharing is allowed, 640 kB as txt). Besides others it also allows Forth to include optional [floating point](float.md) support, however Forth programmers highly prefer [fixed point](fixed_point.md) (as stated in the book *Starting Forth*). Then there is a newer Forth 2012 standard, but it's probably better to stick with the older one.
@ -50,7 +50,7 @@ Note that even the `:` and `;` characters that serve to define new words are wor
Dictionary constitutes one of the most important concept in Forth, it usually stores the words as a [linked list](list.md), starting with the oldest word -- this allows for example temporary shadowing of previously defined words with the same name.
Forth programmers utilize what's called a **stack notation** to document the "signature" of a function, i.e. what it does with the stack (this is important since the language doesn't have the traditional system of named, counted and checked function parameters) -- they write this notation in a comment above a defined word to communicate to others what the word will do. Stack notation has the format `( before -- after )`, for example the effect of the above defined `average` words would be written as `( a b -- avg )` in this notation.
Forth programmers utilize what's called a **stack notation** to document the "prototype" of a function, i.e. what it does with the stack (this is important since the language doesn't have the traditional system of named, counted and checked function parameters) -- they write this notation in a comment above a defined word to communicate to others what the word will do. Stack notation has the format `( before -- after )`, for example the effect of the above defined `average` words would be written as `( a b -- avg )` in this notation.
Some predefined words usually present in Forth systems include:
@ -257,7 +257,9 @@ We can run this simply with `gforth my.fs`, the programs should write `120`.
WIP
The genius of Forth resides under the hood -- to see it one has to study the internal working and see how it all ultimately ties together. So let's start here with some very basic overview of the internals.
The first, immediate glance of elegance of Forth lies in the stack paradigm -- we don't need any brackets in expressions, no operator precedence, there is no distinction between operators and procedures and we don't need a complex expression parser. It's not hard to see the beauty of it, but Forth is not the only stack-based language.
The true, deeper genius of Forth is in the "everything is word" abstraction and how it allows a very elegant implementation, but this is more difficult to see, this resides under the hood -- to appreciate Forth one has to study the internal working and see how it all ultimately ties together. So let's start here with some very basic overview of the internals.
There are several regions of memory, most importantly the parameter stack (the main kind of stack), the return stack and dictionary memory. Dictionary obviously stores the words. **Format of the word in memory** may differ between implementations, but typically a word record has the following fields: