Friday, 2013-11-01
Playing with Proto-J
I discovered this via a post on Eugene Wallingford's Knowing and Doing, worked through the code, and spent a little time playing with it. Amazingly enough, it compiled with only a few warnings on my current gcc, but I tweaked it a little to compile without warnings, to use sizeof so that it might actually compile on 64-bit systems, and added a prompt to differentiate between input and output. I'm posting this introduction to the language, my my touched-up version, and a commentary on the original code.
Arthur Whitney apparently wrote it in one afternoon, so while it is an interesting example of an interpreter, it is woefully incomplete as a language:
- It only accepts single digits (not full integers).
- It evaluates expressions strictly from right-to-left (no grouping).
- Its only arithmetic operation is addition (no negation etc.).
- It has no mechanisms for any sort of control flow or code reuse (only straight line execution).
It uses a single data type, a 0-3 dimensional array, where an array of rank 0 is a scalar. An array has a type flag indicating whether it contains integers or pointers to other arrays.
Each line is a single expression, consisting of a sequence of single-character “words”. A word can be:
- A “noun” - single digit tokenized as a scalar.
- A “verb” - operator tokenized as an integer index into the verb tables. Each verb can have both monadic and dyadic behaviors; its position in an expression determines which is used.
- A “pronoun” - variable name ‘a’ through ‘z’.
Assignment (‘=’) is not a verb but is built into the evaluator. In general the interpreter does no checking, so any spaces or invalid expressions will give bogus results or simply crash.
It has six verbs, and nine of the twelve possible operations are defined:
Verb | Dyad | Monad |
---|---|---|
+ |
a+b (element-wise) | a (identity) |
{ |
b[a] (index) | size(a) (in 1st dimension) |
~ |
[0..a-1] | |
< |
&a (scalar pointer to a) | |
# |
a#b (reshape: a = dimensions, b = fill) | #a (shape (dimensions) of a) |
, |
a,b (concatenate contents to 1-dim) |
So to build an array we use ‘,
’ to concatenate its
contents. If you want a multi-dimensional array you build an array with the
dimensions and assign it to a variable, then use that to reshape the array. So
you get these results (note that the interpreter prints the array dimensions
followed by its contents):
> a=3,3
2
3 3
> b=a#1,2,3,4,5,6,7,8,9
3 3
1 2 3 4 5 6 7 8 9
> c=a#1,2,3,4
3 3
1 2 3 4 1 2 3 4 1
> d=3,3#1,2,3,4
4
3 1 2 3
Note that because of the evaluation order, that last is 3
concatenated with 3#1,2,3,4
.
We can index into arrays, or add them:
> 2{b
3
7 8 9
> 2{d
2
> b+c
3 3
2 4 6 8 6 8 10 12 10
I can't think of a lot that you can do with this without it being hugely verbose. But with a little extension it could be a neat language. Maybe I'll have to try J. I started reading the Primer and it's interesting seeing the similarities and differences.
--Josh Grams <josh@qualdan.com>