Differences between version 30 and revision by previous author of Forth.
Other diffs: Previous Major Revision, Previous Revision, or view the Annotated Edit History
Newer page: | version 30 | Last edited on Thursday, March 29, 2007 1:53:52 am | by AristotlePagaltzis | Revert |
Older page: | version 28 | Last edited on Tuesday, March 20, 2007 5:21:38 pm | by SamuelFalvo | Revert |
@@ -1,66 +1,56 @@
!!! <tt>YOU FORTH LOVE IF HONK THEN</tt>
-[Forth] is a ProgrammingLanguage developed by ChuckMoore in the 1960s (see the [history of Forth | http://www.forth.com/Content/History/History1.htm]). Forth is a [Stack
] based language with a
ReversePolish syntax
. A function call
is very fast as
the arguments are those
on the [Stack] when the program enters
and the return value is left on the [Stack] when it exits. A Forth program consists of many small functions, with just the essentials written in AssemblyLanguage
.
+[Forth] is a [Stack]-based
ProgrammingLanguage developed by ChuckMoore in the 1960s (see the [history of Forth | http://www.forth.com/Content/History/History1.htm]). [
Forth] code is written in
ReversePolish notation, since it works directly with the stack (actually, several stacks)
. There
is no implicit stack management, which means that function calls are
very fast:
the arguments are whatever is already
on the [Stack] when the function is called
and the return value is whatever
is left on the [Stack] at return
.
-[Forth] is used
in embedded systems. It produces very compact code
. A whole
[Forth] interpreter and development
system will fit into 8 kilobytes, easily,
and leave plenty
of room for code. Back when the computer with 8 kilobytes
of [RAM
] that you were to
write programs for was ''also'' the
the computer you had to write programs ''on
'' [Forth] was very popular
.
+[Forth] is defined
in terms of itself more so than probably any other language
. A [Forth] system generally consists of only a tiny kernel
and a small number
of Forth functions written in AssemblyLanguage, but even most
of the compiler is written in Forth, as is the standard library. Real
[Forth
] geeks
write their own [Forth] kernels from
the metal up. (ChuckMoore creates his own [Forth] machines from silicon.) It doesn
't take much effort once you
've absorbed the
[Forth] philosophy – there is shockingly little holding [Forth] up. This is in tune with ChuckMoore's philosophy of brutal simplicity in software engineering
.
-!!! Implementations
+[Forth] produces very compact code. A whole interpreter and development system will easily fit into 8 kilobytes and leave plenty of room for user code. Back when architectures with 8 kilobytes of [RAM] weren't just the computers that you developed ''for'' but also the computers you developed ''on'', [Forth] was very popular. Today it is most popular in embedded systems and other highly constrained environments: f.ex., it is the language of choice for NASA on many satellites and planetary probes, where its compactness and functional correctness (see below in ''Comparison with Haskell'') outweigh the speed of AssemblyLanguage. It forms the basis for the [RPL] language used in HewlettPackard calculators and OpenFirmware and is used in some of UCSD's music courses. It has been used successfully in ArtificialIntelligence research.
-[DragonForth | http://dragonforth.sf.net]:
- [Free] [Forth] compiler for PalmPilot
-[Quartus | http://www.quartus.net/products/forth/]:
- A [Forth] compiler for the PalmPilot
-[GForth | http://www.jwdt.com/~paysan/gforth.html]:
- [GNU]'s Forth.
- It's unusual for a [Forth] in that it comes with a manual.
- [Forth] programmers aren't big on manuals <tt>:-(</tt>
-[PFE | http://pfe.sourceforge.net]:
- It has a VirtualMachine and kernel (see below) written in [C].
- It might be a good one to study.
-[RetroForth | http://retro.tunes.org]:
- Both a ForthOS and a [Forth] for [Linux] systems.
-[bigFORTH | http://bigforth.sf.net/]:
- A native code compiler for [x86] which includes a [GUI] library and form editor.
-
-[Forth] is also the basis for the [RPL] language used in HewlettPackard calculators and OpenFirmware.
-
-
!!! [Forth] Machines
-
- Sentences long extremely and notation Polish reverse in writing about wrong is what?
- <br>— Jarkko Hietaniemi
+!!! Concepts
-''This is a general description of how [Forth] works. It's __different__.
If you like [Brainf*ck] you will like [Forth].''
+''This is a general description of how [Forth] works. It's __different__. If you like [Brainf*ck] you will like [Forth].''
-[Forth] functions are called ''words''. which
are organised in the ''user dictionary''.
+[Forth] functions are called ''words''. They
are organised in the ''user dictionary''.
A [Forth] machine has two stacks. When subroutines (called ''words'' in [Forth] lingo) are called they pop arguments off the ''parameter stack'' and push back return values. The ''return stack'' holds the return addresses of word calls.
-Finally, the input buffer for the [Forth] parser forms an integral part of a [Forth] system.
+Finally, the ''
input buffer''
for the [Forth] parser forms an integral part of a [Forth] system.
-[Forth] programs are written in ReversePolish notation. [Forth] words access
the ''
parameter stack''
directly to fetch
arguments and leave return values. The stack is also used for temporary storage
, as traditionally
there are no local variables in [Forth]. There are words for flipping around values on
the top of the stacks to help you with this
. As you program
in [Forth] you must keep careful
track of what is supposed to be on the stack at every
point, though this is much easier than it first seems (beginners tend to make this more complicated than necessary, thus giving Forth a bad reputation as a "write-only" language). This is all part of ChuckMoore's philosophy of brutal simplicity in software engineering
.
+Words manipulate
the parameter stack directly to perform calculations on their
arguments and leave return values. Traditionally
, there are no local variables in [Forth] (but there are global variables, which are simply pointers stored under a name in the dictionary): the parameter stack is used for all temporary storage
. There are lots of
words for many simple stack manipulations, such as pushing another copy of
the top-most value, dropping it, rotating the stack in either direction, rotating part
of the stack, etc
. Programming
in [Forth] means keeping
track of what is supposed to be on the stack at any
point.
-The ''
dictionary''
is structured also
like a stack; there is a ''here'' pointer, where everything behind it is considered ''allocated'' and part of the runtime system, and everything in front is considered temporary storage at best
.
As words are defined, ''here'' is advanced. When you wish
to recycle memory, you
''forget
'' a
word (usually by executing a word defined by '''
MARKER'''; see the ANSI Forth specification for details
), which resets
''here
'' to that
word'
s definition point
.
+The dictionary is also
structured like a stack. As words are defined, they are added
to the top of the stack. You can
recycle memory by
''forgetting
'', which means dropping all the entries at the top of the dictionary down to some
word you specify
(usually you do this implicitly
by executing a word defined using <tt>
MARKER</tt>
). Sets of words are usually loaded/defined as a unit
, and are usually referred to as a
''vocabulary
'', analogous
to libraries in other languages. The first vocabulary is a tiny kernel of
word definitions written in MachineCode, then there is a standard library vocabulary defined in [Forth], and then optional vocabularies that define a simple text editor, assembler and disk OperatingSystem. (A modern [Forth] system might have a [TCP/IP] stack on there somewhere too.) Some [Forth]
s permit multiple vocabularies to exist concurrently and independently, thus providing namespaces
.
-Some
Forth's permit multiple vocabularies
to exist concurrently
, analogous
to C++ namespaces
. The first vocabulary is
a tiny kernel of word definitions written in MachineCode, then there is a standard library vocabulary defined in
[Forth], and then optional vocabularies
that define
a simple text editor
, assembler and disk OperatingSystem
. (A modern
[Forth] system might have
a [TCP/IP] stack on there somewhere too
.)
+The word <tt>:</tt> tells [
Forth]
to begin compiling the subsequent words found on the input buffer
, and the word <tt>;</tt> then tells it
to stop
. You use <tt>:</tt> to add new words to the [Forth] system until you've created
a high-level
[Forth] vocabulary
that you can easily express your problem in. You just keep going until you've defined
a single word that
, when called, executes your entire program
. [Forth] is very much
a BottomUp language
. :-
)
-There is no syntax in
[Forth], just words for manipulating other words
, the input buffer and the user dictionary
.
+Most words compile to <tt>call</tt> statements. Words that look like integers compile to <tt>push</tt> statements. Some words, however, have flags that tell
[Forth] to execute them immediately while compiling: these create control structures in the ByteCode of a word
, affect parsing
, or perform other compiler or macro functions
.
-The word <tt>:</tt> tells
[Forth] to begin compiling the subsequent
words found on
the input buffer.
+There is no syntax in
[Forth], just words that manipulate other
words and
the input buffer and user dictionary
.
-Some words have flags that tell [Forth] to execute them immediately while compiling: these create control structures in the word. Ordinary words may be compiled into <tt>call</tt> statements, or they may be expanded to native machine language instructions. Words that look like integers may be compiled into the equivalent of <tt>push</tt> statements, or may be embedded into immediate operands of machine instructions. Note that the definition is ''usually'' built piece-meal in the dictionary, so that when <tt>;</tt> is executed, the definition is already finished. Highly optimizing compilers, however, will wait to put anything at all in the dictionary until <tt>;</tt> is encountered, where <tt>;</tt> pushes the new defintion onto the dictionary after proper lexical and parsed analysis. To help generate efficient code, some highly optimizing compilers will even ''infer types'' based on words you call in the definition
!
+!!! Examples
-You use <tt>:</tt> to add new words to the [Forth] system until you
've created a high-level [Forth] vocabulary that you can easily express your problem
in. You just keep going until you've defined a single word that, when called, executes your entire program. [Forth]
is very much a BottomUp language. :-) However, this is absolutely no different from programming in any other language; in C, all programs
''ultimately'' function from a single
<tt
>main()</tt> function. Likewise, in Haskell as well.
+ '
'Sentences long extremely and notation Polish reverse
in writing about wrong
is what?
''
+
<br
>— Jarkko Hietaniemi
-MachineCode statements can be used as
[Forth] ByteCode~s so the machine can execute them directly
. One form of this is called ''subroutine threading''. It is one of a number of approaches to reduce the overhead of interpretation (which spends a lot of time executing call statements)
.
+The following code is a simple text editor from
[Retro Native
Forth | http://retro
.tunes
.org]:
-Real [Forth] geeks write their own [Forth] kernels from the metal up. (I wrote my own, on paper, when I was 14. (I don't think I can do that anymore.) I was working from a [Forth] book and a Z80 opcode table; I didn't have a computer. I still have pieces of it. God knows if it would have worked.) ChuckMoore creates his own [Forth] machines from silicon. It's not ''very'' hard once you've absorbed the [Forth] philosophy. There is shockingly little holding [Forth] up.
+<verbatim>
+0 variable lastBlock
+asmbase $1024 + constant blockBase
-!!! Examples
+: block 512 * blockBase + ;
+: select dup lastBlock
! ;
+: vl dup 40 type cr 40 + ;
+: view lastBlock @ block vl vl vl vl vl vl vl vl vl vl vl vl ;
+: edit select block s drop drop view ;
+: delete select block 512 0 fill view ;
+: edit-line 40 * lastBlock @ block + s drop drop view ;
+: delete-line 40 * lastBlock @ block + 37 0 fill view ;
+</verbatim>
-This right here is a lovely example of
[Forth]: LifeInForth
.
+This demonstrates the preferred programming style in
[Forth]: short words laid out mostly horizontally, just like words in a college dictionary
.
-This more sober
example comes
from the IRC bot (
in [ISForth | http://isforth.clss.net/]):
+The next
example is a utility word
from the IRC bot in [ISForth | http://isforth.clss.net/].
<verbatim>
\ receive up to 512 bytes from bot socket
@@ -83,48 +73,72 @@
drop \ discard buffer address
;
</verbatim>
-Notice the style of code
is predominantly vertical, leading to a program structure that
is intrinsically very
hard to read. The
while loop's condition check, for example,
consists of the overwhelming bulk of the code. This, generally
, is considered very
poor programming
style in Forth
.
+This
is a single long word, written with a
predominantly vertical layout. Such code
is hard to read (eg
. the
while loop's condition check consists of the overwhelming bulk of the code)
, and
is considered poor style.
-Yet another
example, a simple text editor (from
[Retro Native
Forth | http://retro.tunes.org
])
, is much easier to read, and demonstrates the preferred programming method that is more horizontal
. Just as words in a college dictionary are written in only a few lines, and are predominantly horizontal, so too is the code below. Another way of thinking about this is in terms of functional programming, where most definitions are, despite being defined at the global scope, really private to the main word:
+For an almost poetic
example of
[Forth], see LifeInForth
.
-<verbatim>
-0 variable lastBlock
-asmbase $1024 + constant blockBase
+!!! Optimisations
-: block 512 * blockBase + ;
-: select dup lastBlock ! ;
-: vl dup 40 type cr 40 + ;
-: view lastBlock @ block vl vl vl vl vl vl vl vl vl vl vl vl ;
-: edit select block s drop drop view ;
-: delete select block 512 0 fill view ;
-: edit-line 40 * lastBlock @ block + s drop drop view ;
-: delete-line 40 * lastBlock @ block + 37 0 fill view ;
-</verbatim>
+Contemporary [Forth] systems are much more complex than naïve interpreters in order to avoid spending a lot of time executing call statements and to reduce the overhead of interpretation.
-For example
, the definition of "block"
can be likened to the more traditional functional style:
+Instead of compiling words to <tt>call</tt> statements
, they might be inlined, even as MachineCode instructions embedded in
the ByteCode so the target [CPU]
can execute them directly. One form of this is called ''subroutine threading''. Since many target architectures are register-based, numeric literals might
be embedded as immediate operands in MachineCode instructions.
-<verbatim
>
-let block b = blockBase + (512*b)
-
</verbatim
>
+Optimising compilers will wait before putting anything in the dictionary until they encounter the
<tt
>;
</tt
> word, rather than building the definition piece-meal in the dictionary. They can then perform proper lexical analysis and parsing to help generate efficient code. Some highly optimizing compilers will even infer types based on the words called in a word!
-In fact, there are many similarities and dualities between Forth and functional programming languages.
+!!! Comparison with [Haskell]
- * Haskell compiles software to a tree of ''closures,'' basically packets of code
and data that, taken together, form a ''function'' in the mathematical sense
. In Forth
, because parameters are placed on the stack, there
is no need to store free-variables or bound-variables in
the program structure. Hence, a poiner to a closure consists ''only''
of its code pointer; therefore, typical Forth "threaded" code maps 1:1 to Haskell's closure-based execution environment. (The fact that [bigFORTH | http:
//bigforth.sf.net/] and [GHC Haskell Compiler | http
://www.haskell.org] produce binaries that are about equally performant is no coincidence.)
+There are many similarities between [Forth]
and functional programming languages
. For example
, this
is the definition
of <tt>block<
/tt> from the first example
:
- * Forth has issues using local variables, but can maintain global state with ease. Haskell has issues using global state, but can maintain local variables with ease. To address these issues, ANSI Forth introduces a portable locals wordset, while Haskell introduced monads to deal with global state.
Both constructs are fully expressable in the core language, and both address (essentially) different sides of the same problem.
+ <verbatim>
+ : block
512
* blockBase + ;
+
</verbatim>
- * Forth allows the compiler
to be extended by fundamentally altering the compiler in terms of words written in
the base language itself. Haskell utilizes monads for this same purpose.
+This can be likened
to the more traditional functional style:
- * Haskell uses the
<tt>>
>=</tt
> operator to compose the ''right-hand's'' monadic function onto the results returned by the ''left-hand'' computation. This is, save for the threading of state, ''normal function composition.'' In Forth, which is described mathematically as a purely combinator-based language, composition is performed by concatenation -- e.g., simply listing one word after another. Hence, both Forth and Haskell code can be expressed via function composition, and therefore, reasoned about algebraically.
+
<verbatim
>
+ let block b
= blockBase + ( 512 * b )
+
</verbatim
>
- * Forth allows one to freely alter the return stack. Return stack items are (usually) return addresses
, and therefore, (partial) continuations. Freely altering the return stack is dangerous and can produce unstable software. However,
there are nonetheless distinct *patterns* of return stack manipulations you can use to produce _extremely_ compact representations of fairly high-level control flow structures. This introduces the concept of "return conventions," as distinct from "calling conventions." It turns out that Haskell uses return conventions as well, under the hood, to optimize pattern-matching in case and function evaluation
.
+The similarities go far deeper though
, and there are many deep dualities
.
-As you can see,
Forth shares many traits with functional languages
, and therefore doesn't always apply
to the AssemblyLanguage programmer
. In fact, besides embedded devices
, ''music
'' is one
of Forth's application domains, as it is used in some of UCSD's music courses. Forth has successfully been used in artificial intelligence research, and is the language of choice for NASA on many satellites and planetary probes. In these environments, the functional correctness and compactness of Forth weighs more heavily than the use of assembly language
.
+* [Haskell] compiles software to a tree of closures – bundles of code and data that together form a function in the mathematical sense. In [
Forth]
, because parameters are placed on the stack, there is no need
to store free or bound variables in
the program structure
. Hence
, a poiner to a closure consists
''only
'' of its code pointer; therefore, typical "threaded" [
Forth] code maps 1:1 to [Haskell]
's closure-based code
.
------
+ The fact that [bigFORTH | http://bigforth.sf.net/] and the [Glasgow Haskell Compiler | http://www.haskell.org] produce binaries that are about equally performant is no coincidence.
+
+* [Forth] has issues using local variables, but can maintain global state with ease. [Haskell] has issues using global state, but can maintain local variables with ease. To address these issues, [ANSI] [Forth] introduced a portable locals wordset, while [Haskell] uses monads to deal with global state. Both constructs are fully expressable in the core language, and both address (essentially) different sides of the same problem.
+
+ ''''
+
+* [Forth] allows the compiler to be extended by fundamentally altering the compiler in terms of words written in the base language itself. [Haskell] utilizes monads for this same purpose.
+
+ ''''
+
+* [Haskell] uses the <tt>>>=</tt> operator to compose the right
-hand monadic function onto the results returned by the left
-hand computation. Save for the threading of state this is ''normal function composition.'' In [Forth], which is described mathematically as a purely combinator
-based language, composition is performed by concatenation – e.g., simply listing one word after another. Hence, both [Forth] and [Haskell] code can be expressed via function composition, and therefore, reasoned about algebraically.
+
+ ''''
+
+* [Forth] allows one to freely alter the return stack. Return stack items are (usually) return addresses ie. (partial) continuations. Freely altering the return stack is dangerous and can produce unstable software. However, there are nonetheless distinct patterns of return stack manipulations you can use to produce ''extremely'' compact representations of fairly high
-level control flow structures. This introduces the concept of "return conventions," as distinct from "calling conventions." It turns out that [Haskell] uses return conventions as well, under the hood, to optimize pattern matching in case and function evaluation.
+
+!!! See Also
+
+[DragonForth | http://dragonforth.sf.net]:
+ [Free] [Forth] compiler for PalmPilot
+[Quartus | http://www.quartus.net/products/forth/]:
+ A [Forth] compiler for the PalmPilot
+[GForth | http://www.jwdt.com/~paysan/gforth.html]:
+ [GNU]'s Forth.
+ It's unusual for a [Forth] in that it comes with a manual.
+ [Forth] programmers aren't big on manuals <tt>:
-(</tt>
+[PFE | http://pfe.sourceforge.net]:
+ It has a VirtualMachine and kernel (see below) written in [C].
+ It might be a good one to study.
+[RetroForth | http://retro.tunes.org]:
+ Both a ForthOS and a [Forth] for [Linux] systems.
+[bigFORTH | http://bigforth.sf.net/]:
+ A native code compiler for [x86] which includes a [GUI] library and form editor.
-[Forth humour at UserFriendly|http://ars.userfriendly.org/cartoons/?id=20070213&mode=classic]
+Finally, some
[Forth humour at UserFriendly | http://ars.userfriendly.org/cartoons/?id=20070213&mode=classic].
-----
CategoryProgrammingLanguages, CategoryMachineOrientedProgrammingLanguages, CategorySystemsProgrammingLanguages