We are currently working on new rules for what content should and shouldn't be allowed on this website, and are looking for feedback! See Esolang:2026 topicality proposal to view and give feedback on the current draft.

Monky

From Esolang
Jump to navigation Jump to search
This is still a work in progress. It may be changed in the future.

Monky is yet another stack-based language designed over the course of a weekend by User:Menguinponky.

Overview

It draws inspiration from FORTH, FALSE and C, it also uses a data stack and reverse polish notation and is tailored for fast execution by a simple interpreter on a DIY 8-bit machine, while keeping the syntax somewhat readable.

  • All keywords are single special characters
  • All printable ASCII characters have a function
  • Numeric literals are signed integers
  • Single characters and strings can also be pushed onto the stack
  • Input tokens are separated by spaces
  • Extra whitespaces and newline characters are ignored
  • Stack underflow will terminate the program
  • Named variables can be used through the letters a-z
  • Functions can be defined and called using letters A-Z
  • An additional data array is available

Characteristics

Note that although most instructions in the table below have familiar equivalents in their predecessor languages, there are some notable differences:

The comparison operations only consume the top item and leave the previous value on the stack. It is often necessary to compare a value to a range of other values, for example in a switch/case structure, keeping the previous value on the stack easily allows that without having to duplicate it for every comparison.

Neither the print int nor the store var instruction consume the top of the stack, instead the value stays there for further calculation. This also allows print int to be inserted at any point of the program for debugging output without side effects. The pop char instruction on the other hand prints the character and then removes it from the stack.

The instruction character choices are supposed to make the symbols more intuitive to understand:

$ looks like the letter S that swap starts with

^ is above or over the other tokens

% shows two circles after duplication by dup

_ symbolizes the floor that we drop an item to

\ points back towards a value down in the stack to pick

@ symbolizes the rotation of the rot instruction

# is used to count the number of elements on the stack

Just like in FORTH, the logical value false is represented by 0 while true is nominally represented by -1, so that the ~ instruction can be used for logical inversion, though all non-zero values are interpreted as true.

Syntax

Stack effect notation, top of stack to the right:

stack before -- stack after execution (C syntax)

Example notation:

Input → Stack after execution ⇒ Output

Op Name Stack effect Meaning Example
n push int -- n Push signed integer value onto stack 1 → 1
c push char -- c Push ASCII character onto stack a → a
_ drop n -- Pop and discard top of stack 2 3 _ → 2
. print int n -- n Print top of stack as signed integer 3 . → 3 ⇒ 3, -4 . _ ⇒ -4
, pop char c -- Print and pop top of stack as ASCII character a , ⇒ a
' get char -- c Get char from user input and push onto stack (blocking) ' → c
+ add n1 n2 -- n1+n2 Add two top items of stack 1 2 + → 3
- sub n1 n2 -- n1-n2 Subtract top from previous item 3 1 - → 2
* mul n1 n2 -- n1*n2 Multiply two top items 2 3 * → 6
/ div n1 n2 -- n1/n2 Integer divide previous item by top 6 2 / → 3
% dup n -- n n Duplicate top of stack 3 % → 3 3
$ swap n1 n2 -- n2 n1 Swap two top items 1 2 $ → 2 1
^ over n1 n2 -- n1 n2 n1 Copy previous item to top 1 2 ^ → 1 2 1
@ rot n1 n2 n3 -- n2 n3 n1 Rotate three top items to the left 1 2 3 @ → 2 3 1
# count -- n Count and push number of elements on stack 4 5 6 # → 4 5 6 3
\ pick n i -- n i s[i] Pick n-th element out of stack, index 0 picks itself 1 2 3 1 \ → 1 2 3 1 3
& and n1 n2 -- n1&n2 Bitwise AND two top items 12 10 & → 8
| or n1 n2 -- n1|n2 Bitwise OR two top items 12 10 | → 14
~ not n -- ~n Apply bitwise NOT to top item 127 ~ → -128
` xor n1 n2 -- n1^n2 Bitwise XOR two top items 12 6 ` → 10
= equal n1 n2 -- n1 n1==n2 Replace top by true if equal to previous, false if not 1 2 = → 1 0, 3 3 = → 3 -1
< less n1 n2 -- n1 n1<n2 Replace top by true if previous item is smaller, false if not 1 2 < → 1 -1, 2 1 < → 2 0
> greater n1 n2 -- n1 n1>n2 Replace top by true if previous item is greater, false if not 1 2 > → 1 0, 2 1 > → 2 -1
? skip if true b -- Skip next instruction if top is true, consumes logic value 1 2 0 ? + → 3, 1 2 1 ? + → 2
! skip if false b -- Skip next instruction if top is false, consumes logic value 1 2 0 ! + → 2, 1 2 1 ! + → 3
( block start -- Start of a block, jumps to ) unless skipped 3 ( 2 ) → 3, 1 0 ? ( 3 ) → 1
) block end -- End of a block, ( jumps here, no effect if used alone 1 1 ? ( 3 ) → 3
[ loop start -- Start of a loop, ] jumps to this symbol, no effect if used alone [ a , ] ⇒ aaaaa...
] loop end -- End of a loop, jumps back to [ unless skipped 3 [ 1 - ! ] → 0
{ func start -- Start definition of a function body (may span multiple lines) skips to func end { 1 + }
} func end -- End definition of a function body, func start jumps here { "hello" [ % , ! ] }
" string -- 0 c..c Push 0-terminated string onto stack in reverse order "hi" → 0 105 104

The following instructions have multiple functions, depending on the previous instruction:

Op Name Stack Effect Meaning Example
: store var n i -- n Store top value to variable a-z 4 a : → 4
; load var i -- v[i] Load variable a-z a ; → 4
: store data n i -- n Store top value to negative data array index 5 -10 : → 5
; load data i -- d[i] Load variable from negative data array index -10 ; → 5
: func def -- Assign index A-Z to last defined function body { 1 + } I :
; func call i -- Call previously defined function 1 I ; → 2

Examples

Infinite loop

[ ]

Cat program

[ ' , ]

Looping counter

0 [ 1 + . ]

Truth-machine

' 48 - % ? ( [ . ] ) .

Fibonacci sequence

0 . 1 . [ % @ + . ]

Hello, world!

"hellorld" [ , % ! ]

Comment

( "this is a comment" )

Quine

"{ 1 [ \ % ? ( , 1 + ] ) _ _ } P : 34 , P ; 34 , 32 , P ;" { 1 [ \ % ? ( , 1 + ] ) _ _ } P : 34 , P ; 34 , 32 , P ;

Other examples:

print(12 mod 5) → 12 5 ^ ^ / * - . → 2
view(stack) → # [ \ . _ 1 - % ! ] _
if(a==5){print(1)}else{print(2)} → a ; 5 = % ? ( 1 . ) ! ( 2 . )
i=5; do{print(i--)}while(i) → 5 [ . 1 - % ! ]
i=5; while(i){print(i--)} → 5 [ % ? ( . 1 - ] )

Note that blocks and loops are allowed to overlap, like in the last example above.

Computational class

Although no definite proof exists yet, the language is assumed to be Turing-complete.

Limitations

Loops and blocks may not span multiple lines unless within a function.

The language does not allow recursive function calls, this is by design because these structures are rarely indispensable in practical programs, functions calling other functions are fine though.

Interpreter

An interpreter is under development and can be found in a public GitHub repository: https://github.com/0xCAFEAFFE/Monky