Maentwrog

:According to the description of the language at Cat's Eye Technologies at the time this article was written, there was no documentation and there weren't any canonical example programs, so this page was originally 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. This wiki page was subsequently adopted as the official documentation for the language.
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. 
Prefix	Action 	Example	Result
= 	Assign to variable	=foo 	A value popped from the stack is assigned to the variable foo.
@ 	If 	@bye 	Pop value, stop the program (see predefined words) if it isn't 0.
[ 	While 	[xyz 	Pop value, if it's not 0 execute word xyz, then pop another value and do it again; continue until a 0 is popped.
$ 	Repeat 	$. 	Pop value, then output that many values from the stack.
==Predefined words==
Word 	Stack Effect	Description
bye 	 	Stop program immediately.
rem ... ; 	 	Comment. (Ignore all words between rem and ;.)
: word ... ;	 	Define a new word.
debug 	 	Turn on debugging (outputs all words executed).
vars 	 	Output a list of currently defined variables and their values.
words 	 	Output a list of currently defined words.
alloc 	ptr 	Allocate memory for n C longs, returns a pointer.
free 	- 	Free memory at pointer.
size 	n 	Push stack size.
dup 	a a 	Duplicate top of stack.
swap 	b a 	Swap the two topmost stack values.
pop 	- 	Remove top value from stack.
get 	value 	Push value at pointer to stack (C *ptr).
put 	- 	Store value at pointer (C *ptr = val).
rnd 	n 	Push random value.
> 	(a>b) 	Push 1 if a is greater than b, else 0.
< 	(a<b) 	Push 1 if a is less than b, else 0.
== 	??? 	See note at the end.
. 	- 	Pop a value, output as integer, adding a newline.
.. 	- 	Pop a value, output as an ASCII character.
mod 	(a%b) 	Modulo.
+ 	(a+b) 	Addition.
- 	(a-b) 	Subtraction.
* 	(a*b) 	Multiplication.
/ 	(a/b) 	Division, result is rounded towards 0.
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()); so it should be acting as boolean equality. However, actually trying to use it, it acts like pop. It looks like a bug in the implementation.
==Example programs==
====Hello World====
: puts dup .. @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
==External resources==
* 
* maentw.c in Maentwrog distribution on Codeberg
Category:1993 Category:Implemented Category:Low-level Category:Languages Category:Stack-based