Sorry for the missed weeks of friday pathological programming language columns. To be honest, I’m running out of languages. I’m sure there must be more, but my usual sources (dealers?) are running out – so send links!
Anyway, today I’m going to look at a really simple one, which I find fun. It’s
not an overly exciting language, but it is a language which is has semantics almost as
trivially simple as [BrainFuck][bf], but which ends up looking almost as much like line-noise as [TECO][teco]. It’s called [Betterave][betterave].
Betterave is a very simple language which is based on prefix operators. (The authors calls them functions, but they’re not.) It uses a storage system with 26 variables (one for each letter of the alphabet), and a dictionary of strings indexed by number.
There are 8 kinds of operations in Betterave, and 2 kinds of control flow operators.
Here’s the basic list of operators:
* `0-9` – a single digit in Betterave is a zero-parameter operator that returns
the value of the digit. This is the only way to do numeric literals in betterave;
to create a literal like 42, you’d need to use multiple literals and
arithmetic operators: `*76`.
* A literal string written in quotes adds a new string to the dictionary, and
returns the index of the string.
2. **Arithmetic**: `+`,`-`,`*`,`/`,`%` – binary operators that add/subtract/multiply/divide/modulo
the values of the next two expressions.
3. **Comparisons**: `=`, “ – compare the value of the next two expressions,
returning 1 if the first is equal/less than/greater than the other.
4. **Input**: “`:`” reads a number from the command-line, and returns it; “`;`” inputs
a string, adds it to the end of the string dictionary, and then returns its index.
5. **Output**: “`.`” prints the value of the following expression as a number; “`,`” prints it as
an ASCII character.
6. **String Operations**:
* *String Append*: The string append commands are “`&`” and “`#`”.
They’re both binary operators. Their first parameter is the index of a string
to modify, and the second is a number. “`#`” interprets the second parameter
as a number, and the string representation of that number is appended to the
specified string; “`&`” interprets the second character as the ASCII code of
a character, and appends the character to the specified string.
* _Delete character_: “” takes one parameter, which is the index of a string
to modify. It removes the first character from the string, and then returns
the value of that character.
* _Delete string_: “`_`” takes one parameter which is a string index,
deletes that string from the dictionary, and returns the index of the deleted
string. The index of strings after it are modified by this.
* *Print string*: “`$`” takes one parameter which is the index of a string in
the dictionary, and prints that string.
7. **Variable Operations**: there are 26 variables, a through z. A variable name
in uppercase assigns the value of the next expression to the variable; a variable
name in lowercase returns the value of the variable.
There are two control flow operators in Betterave: loop, and conditional.
* __Loop__: “`[expr1 | expr2]`”: this evaluates expr1; then expr2. If expr2 returns
a non-zero value, then it repeats. Loops nest like you’d expect.
* __Conditional__: “`? expr1 expr2 !`”. Evaluates expr1. If expr1 evaluates to
non-zero, then it evaluates expr2; otherwise, it skips to the expression following
the next “!”. Conditions do not nest: on false, it will just skip to the
next “!”, not to a matching “!”. So, for example, “`?0 ?=10!.5!.6`” will
output 56: 0 evaluates to zero (false), so it skips to the next “!”, after which
it “.5” and then “.6”.
So. First example, as usual, is “Hello World”.
Pretty simple. A more interesting version:
This stores the string “Hello, World!” in the string dictionary at index 0, and
stores 13 (the number of characters in the string), into variable A. Then it starts a loop. Inside the loop, it removes and outputs the first character of string 0, then subtracts one from A, and repeats the loop if A>0. So it outputs the characters in sequence.
How about a beautifully line-noisy fibonacci series?
* Read a number from the keyboard, and store it in A.
* Set B (which will store the result) to 1.
* Start a loop:
* Multiply B by the current value of A
* Subtract one from A
* Repeat as long as a is greater than 0.
* Output B, followed by a carriage return.
*(Note: a couple of typos were corrected in this post.)*