MoreMathRPN

From Esolang
Jump to navigation Jump to search
2 M's are placed above the letters "RPN" all in black, placed into a light blue to blue gradient top to bottom
Logo for MoreMathRPN

Note: unless otherwise specified, assume all "or" is the exclusive or.

MoreMathRPN (abbreviated MMRPN) is a stack based imperative language created in 2023, create by Calculus is fun (talk).
Originally for simple linear algebra, it has since grown to be turing complete. It is inspired by FALSE and its relatives, whilst also being more human friendly.

MMRPN is line independent, without labels or line numbers, and has no variable scoping.

Commands

Each line must have only one command or comment.

Literals

This language has rational and string literals, there are 4 ways to input a Rational:

  • Integers e.g. 10
  • Ratio of 2 integers e.g. 3/5
  • Terminating decimal e.g. 3.894
  • Recurring decimal e.g. 1.1[32] -or- 0.[3]

You can prepend a hyphen to negate the value, and periods can be substituted with commas.
String literals can only be in an instruction's parameters,
they are double quoted strings that allow spaces; most literal UTF-8 characters; along with \\, \", and \n escape characters.

Instructions

There are 2 types of input a command has, Parameters and Arguments. Parameters are integers placed after the command and deliminated by spaces. Arguments are from the stack and can be rational (R) or matrices (M), if needed; variables will be denoted [top] a, b, c, ... [bottom]

Standard operations

Operation symbol/name Description / Formula Parameters Arguments
" Comment (see examples below) None None
+ Addition None 2 R or 2 M
- Subtraction (b - a) None 2 R
* Multiplication None 2 R, 2 M, or 1 R and 1 M
/ Division (b / a) None 2 R
% Remainder (b % a) None 2 R
int Integer part None 1 R
floor Round down None 1 R
ceil Round up None 1 R
den Denominator None 1 R
gcd Greatest common divisor None 2 R
lcm Least common multiple None 2 R
step Greater than zero (a > 0 → 1, a <= 0 → 0) None 1 R
compare Comparison (b - a < 0 → -1, a == b → 0, b - a > 0 → 1) None 2 R
# Stack height None None
>> Copy Depth None

Stack manipulation

Operation symbol/name Description / Formula Parameters Arguments
-> Pull Depth None
<- Push Depth None
del Delete Depth None

Matrices

Operation symbol/name Description / Formula Parameters Arguments
m Matrix Columns, rows columns * row R
addRow Row addition Row from, row to 1 R and 1 M
scaleRow Row scaling Row 1 R and 1 M
swapRows Row swapping Row from, row to 1 M
T Transpose None 1 M
inv Inverse None 1 R or 1 M
ref Row echelon form None 1 M
ind Value at index Column, row 1 M
rip Rip last column None 1 M
flip Flip across rows None 1 M
dim Dimensions None 1 M
dot Dot product None 2 M
hadamard Hadamard product None 2 M
kronecker Kronecker product None 2 M
outer Outer product None 2 M

Loops

Operation symbol/name Description / Formula Parameters Arguments
jmp Jump to Offset None
repeat Repeat loop End Count None
next Next iteration None None
>>> Iteration number Loop Depth None
break Break out of current loop None None
leap Break out of current loop, then jump Offset None

Variables

Variable names can not have spaces nor start with ".

Operation symbol/name Description / Formula Parameters Arguments
hold Store top of stack as variable Name 1 R or 1 M
place Place copy of variable to stack Name None
lose Remove a variable Name None
exists Exists (does variable exist? yes → 1, no → 0) Name None

IO & strings

Operation symbol/name Description / Formula Parameters Arguments
chars Converts a string's UTF-8 code points in reverse order (end is at the bottom), then tops it with the string's length. String None
inputR Prompts the user to input a number in a valid format as described above, if invalid, the program will ask again. The prompt message is an optional parameter, and not giving it should default to a generic message. Prompt (optional) None
inputS Prompts the user to input a string, converts the response's UTF-8 code points in reverse order (end is at the bottom), then tops it with the string's length The prompt message is an optional parameter, and not giving it should default to a generic message. Prompt (optional) None
outputC Outputs a single character whose code point is the parameter Code point None
outputS Outputs a string String None
outputV Pops and outputs a rational or matrix, format depends on implementation None 1 R or 1 M

Dynamic parameters

You might be thinking how if-else statements are going to happen in this language; fortunately, parameters can be controlled by the program, these get rounded towards 0 if the rational is not an integer.

  • ]n grabs the nth item from the top of the stack
  • [n grabs the nth item from the bottom of the stack
  • $name uses a variable

Behavior

Certain commands have specific actions given interesting conditions, here's a list of those conditions.

Repeat without next

If a repeat is missing a corresponding next, It is inferred to be at the end of the program, but the loop won't repeat. Either break or leap will end the program if run in an incomplete repeat statement.

repeat 10
 3
 5
 break
 5
 1
 "next statement inferred here!

Nested loops

repeat ... next blocks can be nested, helpful for simplifying advanced patterns

repeat 10
 repeat 10
  "outer
  >>> 1
  "inner
  >>> 0
  +
  2
  -
 next
next
m 10 10

Out of the loop

calling break or leap outside the active loop results in an error.
It is recommend to keep looping code in the repeat...next block.

repeat 10
 jmp 2
next
"Error!
break

Leaping back

leap with a negative parameter are treated like breaks, this is to dissuade the act of jumping into the repeat you just left.

"You would expect this to be an infinite loop, but it isn't.
repeat 1
 "I'm now a break!
 leap -2
next

Zero jmp

When jmp is given a parameter of 0, jmp does nothing, this is so you don't have to write 1 + every time you use it. See examples below.

Examples

More examples can be found here

Creating conditions

Conditions are often created via the step or compare instructions, then by evaluating an polynomial function and feeding that into a jmp, complex branching behavior can appear.

5
0
"enter loop 5 -> 1
del 0
"more code here...
1
-
>> 0
step
"adjust this when you add instructions above!
-7
*
"if jmp is given a parameter of 0, it does nothing
jmp ]0
del 0
"exit loop

You can also use repeat with a parameter of 1 or 0, to run or skip a block of lines.

"0 or 1
0
repeat ]0
 1
 2
 3
 4
 "dummy
 1
next
del 0

Fibonnaci

This program repeatedly adds the previous 2 numbers forever

0
1
>> 1
>> 1
+
jmp -3

We can use the repeat instruction to limit the repetitions

0
1
"repeat 50 times...
repeat 50
 "indentation of code is optional, but preferred
 >> 1
 >> 1
 +
next

Factorial

Calculating the factorial is also easy

"argument
5
1
repeat ]1
 >>> 0
 *
next
del 1
"120 should be alone

Coefficients of a cubic

Using the matrix commands, one can solve a linear system quickly.

"degree + 1
repeat 4
 1
 >>> 0
 1
 -
 "degree
 repeat 3
  >> 1
  >> 1
  *
  -> 1
 next
 del 0
 m 1 4
next
"degree
repeat 3
 aug
next
T
flip
inv
"f(0)
0
"f(1)
1
"f(2)
4
"f(3)
-13
m 1 4
*
"x^3, x^2, x^1, x^0

Cat

Takes the input and returns it; Unless you send the empty string, then it terminates.

inputS
hold len
step
3
*
jmp ]0
del 0
jmp 7
del 0
repeat $len
 outputC ]0
 del 0
next
jmp -13

99 bottles of beer

Use the new IO commands and get very hammered.

99
repeat 98
 >> 0
 >> 0
 1
 -
 >> 0
 <- 3
 <- 3
 outputV
 outputS " bottles of beer on the wall,\n"
 outputV
 outputS " bottles of beer.\nTake one down pass it around,\n"
 outputV
 outputS " bottles of beer on the wall.\n"
next
del 0
1
1
outputV
outputS " bottles of beer on the wall,\n"
outputV
outputS " bottles of beer.\nTake one down pass it around,\n"
outputS "Oops, we ran out of beer!"

Fractran interpreter

It's fitting that a language based on rationals can run Fractran. Here's John Conway's prime program.

"program
17/91
78/85
19/51
23/38
29/33
77/29
95/23
77/19
1/17
11/13
13/11
15/14
15/2
55/1
#
hold len
del 0
m $len 1
"input
2
"loop
-> 1
>> 1
repeat $len
 "read fraction
 >>> 0
 1
 -
 -> 2
 ind ]1 0
 -> 1
 <- 3
 del 1
 "check validity
 >> 1
 *
 >> 0
 1
 %
 step
 2
 *
 jmp ]0
 "success
 leap 2
 "failure
 del 0
 del 0
next
"exit
jmp 4
"update input
del 0
del 1
"iterate again
jmp -27

Because we can run Fractran directly, this proves MMRPN is Turing-complete

Ackermann function

This function requires recursion; with a little planning however, you can use the stack as a call stack too!

"m
3
"n
3
"----
43
jmp 3
"return path
-> 1
jmp ]0
"begin A(m,n) form m, n, return location
<- 2
"m==0
>> 1
step
6
*
jmp ]0
"true
del 0
"n + 1
del 1
1
+
"return
jmp -12
"false
"n==0
del 0
>> 0
step
10
*
jmp ]0
"true
del 0
del 0
1
-
1
25
"A(m-1,1)
jmp -23
del 0
"return
jmp -27
"false
del 0
>> 1
-> 1
1
-
34
"A(m, n-1)
jmp -32
del 0
-> 1
1
-
-> 1
41
"A(m-1,A(m,n-1))
jmp -39
del 0
"return
jmp -43
"end A(m,n)
del 0
outputV

Examples elsewhere on this site

Implementations

JavaScript MMRPN Interpreter by Calculus is fun (talk)!