MP-FORTH is a language created to be a quick, useful language that will be fun and pain-free to develop both on small-screen devices (read: iPhone) as well desktops. MP-FORTH stands for Multi-Precision FORTH, because it is essentially a re-creation of FORTH with a heterogeneous stack, designed for interactive use. It is linguistically similar to the way that most HP RPN calculators do programming, with a few tricks up its sleeves.
MP-FORTH, like python, and many other modern languages, uses GMP and MPFR to do unlimited arithmetic. This means that you're limited by available RAM, not 32 or 64 bits. Want to take 2^65 and work on it as an integer? Do it! (This would be “2 65 pow” in MP-FORTH). MP-FORTH is designed for use on small devices, so you can set keys for commonly used functions and words, and program without having to type, type, type. Really, MP-FORTH is also a different way of thinking about programming, as you'll find out. Oh, and if you bought TouchRPN (thanks!), you're stuck with it! Haha!
Getting Started To get started knowing MP-FORTH it's probably best to start with KeyRPN, a desktop front-end for MP-FORTH. It's a lot easier to peek, poke, and mess around with it than it is to try to do it with the keyboard mode in TouchRPN. Download KeyRPN (sorry, MacOSX only so far, port it!).
Okay, now that you have a terminal in front of you, let's add some numbers:
1 1 +
Giving you the result
Surprised? In MP-FORTH the operands usually precede the operator (numbers are operands, addition is an operator). This holds for most of the operators and functions. Let's take the sin of a pi/2:
pi 2 / sin
There is no real syntax to MP-FORTH, everything is simply whitespace delimited. Everything is separated by whitespace. This is logical to a fault. For example, the string creation operator is a double-quote, terminated with a double quote. This means that
” hello ” represents the string “hello”, and
” hello world ” represents “hello world”, but
” hello world” is an unterminated string (the second quote is considered part of the world token) that will eat all of your code, and most likely throw a warning.
FORTH comments are enclosed by parenthesis. ( and ) on their own.
In RPN lingo, and FORTH lingo, the top of the stack (conveniently at the bottom of most displays of the stack…), is X, the second is Y, and the third is Z. So the + operator takes X and Y, adds them, and pushes them in to X.
Words are the FORTH name for functions, they are groupings of code that execute on the stack. There is no notion of arguments, just the stack. So, words take any number of operands, remove them from the stack, and spit out any number of results, back on to the stack. For example, ”+” takes two operands, and returns one (the sum of the two operands). Some functions are more complex, taking 3 or 4 operands. More than that is generally frowned upon, but is not impossible.
To make a word, use ”: <wordname>”. Word names can have any non-whitespace characters in them. Yes, ANY characters, including quotes, brackets, numbers, underscores, etc. They probably shouldn't start with a number. After the word name, just stick MP-FORTH code until the function is done, then terminate with a ”;” on its own (remember, everything is whitespace delimited). Here we make a word that adds 1 to the X register of the stack. The code to do this is simply:
: 1+ ( add 1 to X ) 1 ( push 1 onto the stack ) + ( add X to Y );
or, without comments,
: 1+ 1 + ;
The first comment after the word name is the “documentation” part of the word, which you can access using the “doc” keyword (syntax
doc <wordname>, it is a lookahead operand). All other comments just explain what's going on.
Once you have defined this function, you can call it anytime by simply using its name, 1+. For a more real example, let's take a look at how MP-FORTH does the trigonometric functions:
: sinh dup exp swap neg exp - 2 / ;
: sin i * sinh i / ;
Basically, MPF defines sin in terms of the complex side of the hyperbolic sin, which in turn is defined in terms of exponentials.
MP-FORTH allows you to define both constants and variables. The differences between these two concepts are subtle. Let's start with the simpler idea, constants.
Constants are created with the “constant” word. It is a lookahead word that works like this:
<value> constant <name>
It takes the value in the X register, and stores it in a word, <name>. It works exactly the same (exactly the same), as defining a word with <name> and <value> as the code:
: <name> <value> ;
Variables work slightly differently than constants. They are more useful, but also slightly harder to grasp and use. You create a variable with the word:
This created a variable of name name. If you now use the word name, you'll see something odd on the stack, VAR: (null). This is because there is nothing stored in the variable yet. To store something in it, use the ! word, like so:
<value> <name> !
The ! operator takes the value in Y and stores it to the variable reference in X.
To recall, use the @ operator:
Comparison works using the <, > and = operators. They work as expected:
2 1 < ( results False )
2 1 > ( results True )
2 1 = ( results False )
Conditionals are done using the
then keywords. The
if block takes the X register of the stack, and if it evaluates to True, executes everything up until an
else or a
then clause. If an
else keyword is present, it will skip everything between
then. If X evaluated to False, then it will execute the code between
<truth> if ( executed if <truth> is True ) else ( executed if <truth> is false ) then
<truth> if ( executed if <truth> is True ) then
You can use the
not operator to flip conditionals.
In MP-FORTH, the
repeat keywords control looping. The options are as follows:
begin <block> again ( Executes <block> forever )
begin <block> ( flag ) until ( Executes until the flag is true )
begin <block1> ( flag ) while <block2> repeat ( more later )
The first example,
begin <code> again, loops <code> forever. The second expects a flag at the end of <code>, which it check to see if it should keep looping. So, if the code doesn't leave an extra flag at the end, that will eat up the stack until an error occurs, or until it sees a False value.
begin until will eat up all true values on the stack. The last example basically executes <block1> (which it expects a flag out of), each time it's true, also executing <block2>. Once the flag executes to false, it doesn't execute <block2> and exits out.
As of 1.1.3, MP-FORTH supports multi-base entry and display of integers. Integers can be entered in binary, octal, decimal, or hexadecimal:
0b101011 - bin entry
0o172645 - octal entry
1389750 - dec entry
0x1248AFC - hex entry
The display base can be any base, and is set using the
setibase - sets the display base to the X register. Ex:
2 setibase : sets base to binary
8 setibase : sets base to octal
10 setibase : sets base to decimal
16 setibase : sets base to hex
setibase works with any integer between 2 and 62.