Maentwrog

NOTE: According to the official page at Catseye, there is no documentation and there aren't any canonical example programs, so this page has been written according to the source code and the behaviour of the official interpreter, which appears to be the closest thing to a language definition there is available.

Maentwrog is a programming language created by Chris Pressey, and implemented by him in August 1993. According to the readme for Shelta, it was the first language he designed. It bears a resemblance to Forth, in that it is a stack-based language with user-definable whitespace-separated words. Even for an esoteric language, it is low-level: it allows direct OS-level memory access using pointers, as in C. It is the predecessor of Befunge.

Syntax
A Maentwrog program consists of a series of words, separated by whitespace. Words can contain any character except whitespace. The way these words are executed depends on the character they begin with.


 * A word that consists of digits is taken as an integer and pushed. A minus sign may be used to make negative numbers, so 25 and -14 are words that push 25 and -14 onto the stack. Extra characters at the end of the word are allowed, so 25abc and 25.14 both also push 25.


 * A word that isn't a number is treated as either a function or a variable. If the word is defined as a function, it is executed; if it's a variable, its current value is pushed to the stack. Using an undefined word results in an error, though this doesn't stop further execution of the program.


 * To define a word as a function, use the syntax : new-word words to execute ; (as in Forth). Redefining a word is not allowed, and neither are nested function definitions.


 * To define a word as a variable, use the syntax *varname. This must be done before using a variable.

Additionally, words (except number words) can take one of a list of prefixes, changing how the word is executed.

Predefined words
Note: I have no idea what the == word is supposed to be. In the official interpreter, maentw.c, it seems to be defined as push(!pop == !pop)</tt>; so it should be acting as boolean equality. However, actually trying to use it, it acts like pop</tt>. It looks like a bug in the implementation.

Hello World
@puts ; 0 10 33 100 108 114 111 119 32 44 111 108 108 101 72 puts

Fibonacci
*a *b *c 0 =a 1 =b
 * fib a b + =c c . b =a c =b c 100000 < @fib ;

1 . fib

Prime number generator
A bigger example (I couldn't resist...) rem array functions ;
 * dim 2 * alloc ;
 * idx 8 * + ;

rem equality ;
 * eq2 pop 0 ;
 * eq - 1 swap @eq2 ;

rem test each element in the array ;
 * walkarr2 i 1 + =i i cursz < @walkarr1 ;
 * walkarr1 curn arr i idx get mod 0 eq =fd fd 0 eq @walkarr2 ;
 * walkarr 0 dup =i =fd walkarr1 ;

rem implementation of algorithm ;
 * sieve2 arr cursz idx curn put curn . cursz 1 + =cursz ;
 * sieve1 walkarr fd 0 eq @sieve2 curn 1 + =curn cursz maxsz < @sieve1 ;
 * sieve *i *fd *curn *cursz 2 . arr 2 put 3 =curn 1 =cursz sieve1 ;

rem memory handling ;
 * primes *arr *maxsz dup =maxsz dim =arr sieve arr free ;

rem change the number to change the amount of primes ; 25 primes