Calculator.app
Paradigm(s) | Concatenative, imperative |
---|---|
Designed by | User:RocketRace |
Appeared in | 2023 |
Memory system | Stack-based |
Computational class | |
Reference implementation | Calculator.app |
File extension(s) | {{{files}}} |
Calculator.app is a pseudo-concatenative, stack-oriented programming language by User:RocketRace that tastefully reimplements the macOS default calculator app by the same name. This language exists to demonstrate the (surprisingly) rich feature set of the app, such as RPN support, unit conversions, and bitwise operations.
Examples
The following program prints fibonacci numbers when executed in a loop on persistent state (as the reference implementation does).
Scientific enter 1 enter 5 2Vx + enter 2 / enter mr y^x enter 1 +/- enter 5 2Vx - enter 2 / enter mr +/- y^x - enter 5 2Vx / Programmer [10] Large-Type Scientific drop enter 1 m+ drop
The following program takes as an argument elements X and Y on the stack (pushed in that order), and returns with X%Y on the stack.
Scientific Rad enter Rv x<->y R^ / enter pi * cos 2nd cos^-1 2nd enter pi / *
Reference
A Calculator.app program is a UTF-8 string of whitespace-delimited words, each word representing a button available in the calculator app. These buttons each affect the state of the program in some way. Some buttons may cause an error to be raised (such as with invalid values or not enough values on the stack to perform an action), which halts execution. Many buttons have both a pretty-unicode and an ASCII representation.
The below aims to describe the reference implementation, which is the primary source of truth on the language.
Deviations from source material
There are some deviations from the app itself when translating its behavior into an esolang. Calculator.app is not a full recreation of the source app. There are a number of features in the original that are confusing, janky, or otherwise annoying to program in (and especially annoying to implement), and have been removed:
- The specific behavior of
C
andAC
- Implicit bitwidth narrowing
- Entering values in RPN mode is inconsistent across numeric & programmer modes
- The way numbers are converted while entering Programmer mode is lossy:
- When exiting Programmer mode, numbers are not always converted to doubles; until an operation is performed on them, they are displayed and stored as their 64-bit integer value (which may not be representable as a float).
- The stack is sometimes cleared when enabling and disabling RPN input.
- The ASCII and Unicode output options are flags that toggle a permanent display to the side of the number.
- There are some buttons with ambiguous labels, such as
C
. - (Infix functions were also removed. It's a stack language now.)
State
The runtime has two main sources of data: Stack and State. State contains flags and registers that alter the behavior of buttons.
- Current mode (Basic, Scientific or Programmer)
- Digit input data (decimal point presence & location, visible digits)
- Base in programmer mode
- Angle and Palette in scientific mode
- The contents of the memory cell in scientific mode
The stack contains either 64-bit unsigned integers or 64-bit floating point numbers, based on the current mode. (Floats in basic / scientific, ints in programmer).
Buttons
Below is a list of buttons by category and their actions.
Stack
Stack buttons are available in every mode.
x↔︎y or x<->y |
Swap the top 2 elements of the stack |
R↓ or Rv |
Roll the stack “down”, i.e. pop an element normally and push it to the wrong end of the stack. The wording here is bad because the original app visualizes the stack as growing downwards, and hence the "top" of the stack is in fact at the bottom. "Normally" refers to the default action of the stack, and "wrong" refers to doing things at the opposite end (which is not a feature of stacks but oh well) |
R↑ or R^ |
Roll the stack “up”, i.e. pop an element from the wrong end of the stack and push it normally |
drop |
Drop the top of the stack. If there is only 1 element on the stack, push 0 to the stack afterwards. (This means the stack is never empty.) |
enter |
Duplicate the top of the stack |
Basic arithmetic
Basic arithmetic is available in every mode. Note that in programmer mode, these operations can overflow.
+ |
Pop two elements and push their sum |
- |
Pop one element, pop another, push the second element minus the first |
× or * |
Pop two elements and push their product |
÷ or / |
Pop x, pop y. If in programmer mode and x is 0, then push y and push x. Else, push y divided by x. This makes integer division by zero a complete noop instead of erroring. |
Numeric modifiers
These buttons are available in basic and scientific modes.
⁺∕₋ or +/- |
Negate the top of the stack |
% |
Divide the top of the stack by 100 |
Digit buttons
The behavior of the numeric buttons and the decimal point (including double digit buttons in programmer mode) are influenced by digit input data. When the digit state is clear, pressing a digit will replace the top of the stack with that digit. Pressing additional numbers after that point will concatenate them with the top of the stack. Pressing the decimal point after zero or more digits inserts the decimal point at the specified position. In programmer mode, decimal points cannot be entered, and the digits a~f can only be entered in hexadecimal base.
0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , or 9 : When in basic or scientific mode |
Apply the behavior of the given digit |
. or , : When in basic or scientific mode |
Apply the behavior of the decimal point |
0 , 1 , 2 , 3 , 4 , 5 , 6 , or 7 : When in Programmer mode and any base |
Apply the behavior of the given digit |
8 or 9 : When in Programmer mode and decimal or hexadecimal base |
Apply the behavior of the given digit |
a , b , c , d , e , or f : When in Programmer mode and hexadecimal base |
Apply the behavior of the given digit |
00 : When in Programmer mode |
Apply the behavior of the 0 digit twice |
ff : When in Programmer mode and hexadecimal base |
Apply the behavior of the f digit twice |
Clear
Clear buttons are available in every mode.
C |
Set the top of the stack to 0, clear digit data |
AC |
Clear the stack and state |
⌘Q or Q |
Quit the program successfully |
Mode
Mode buttons are available in every mode.
Basic |
Set the mode to basic. If the previous mode was programmer mode, then turn every int in the stack to the float closest to it in value |
Scientific |
Set the mode to scientific. If the previous mode was programmer mode, then turn every int in the stack to the float closest to it in value |
Programmer |
Set the mode to programmer. If the previous mode was not programmer mode, then truncate every float on the stack into an 64-bit integer, taking only the bottom 64 bits of the int |
Programmer' |
Set the mode to programmer. If the previous mode was not programmer mode, then reinterpret the bitwise data of the doubles on the stack as int data |
Angle
Angle buttons are available in scientific mode. The default angle mode is degrees. This influences the behavior of trigonometric functions.
Rad : When the angle mode is degrees |
Set the angle mode to radians |
Deg : When the angle mode is radians |
Set the angle mode to degrees |
Palette
The palette button is available in scientific mode. The default palette is "first". This enables and disables certain buttons.
2ⁿᵈ or 2nd |
Toggle the current palette from first to second, or from second to first |
Memory cell
The memory cell buttons are available in scientific mode. The memory cell is initialized with the value 0.
mr |
Replace the top of the stack with the contents of the memory cell |
m+ |
Add the value at the top of the stack to the memory cell |
m- |
Subtract the value at the top of the stack from the memory cell |
mc |
Set the memory cell's value to 0 |
Base
The base buttons are available in programmer mode. The default base is hexadecimal.
[8] |
Set the base to octal |
[10] |
Set the base to decimal |
[16] |
Set the base to hexadecimal |
Output
The output buttons print results to standard output.
Large-Type : When in basic or scientific mode |
Print the number at the top of the stack to standard output (with a newline). |
Large-Type : When in programmer mode |
Print the number at the top of the stack to standard output (with a newline). The output is formatted in the current base. |
[ASCII] : When in programmer mode |
Print the ASCII character corresponding to the lowest 7 bits of the number at the top of the stack, to standard output (without a newline). |
[Unicode] : When in programmer mode |
Print the Unicode scalar value corresponding to the lowest 21 bits of the number at the top of the stack, to standard output (without a newline). Output is encoded in UTF-8. Single surrogates are not valid characters and therefore cause an error. |
These buttons are available in scientific mode.
Rand |
Set the top of the stack to a uniformly random number between 0 and 1 |
E |
Set the top of the stack to euler's constant e |
π or pi |
Set the top of the stack to the circle constant pi |
EE |
Pop x, pop y, push (y * 10^x) |
¹∕ₓ or 1/x |
Pop x, push one divided by x |
x! |
Pop x, push x factorial (extended to real domain using the gamma function) |
x² or x^2 |
Pop x, push x squared |
x³ or x^3 |
Pop x, push x cubed |
yˣ or y^x |
Pop x, pop y, push y to the power of x |
²√x or 2Vx |
Pop x, push the square root of x |
³√x or 3Vx |
Pop x, push the cube root of x |
ˣ√y or xVy |
Pop x, pop y, push the xth root of y. (note that there is no yVx button) |
First palette
These buttons are available in scientific mode, when in the first palette.
sin |
Set the top of the stack to the sine of the top of the stack, using the current angle mode |
cos |
Set the top of the stack to the cosine of the top of the stack, using the current angle mode |
tan |
Set the top of the stack to the tangent of the top of the stack, using the current angle mode |
sinh |
Set the top of the stack to the hyperbolic sine of the top of the stack |
cosh |
Set the top of the stack to the hyperbolic cosine of the top of the stack |
tanh |
Set the top of the stack to the hyperbolic tangent of the top of the stack |
ln |
Pop x, push the natural logarithm (base e) of x |
eˣ or e^x |
Pop x, push the exponential function (exp) of x |
10ˣ or 10^x |
Pop x, push 10 to the power of x |
log⏨ or log10 |
Pop x, push the logarithm base 10 of x |
Second palette
These buttons are available in scientific mode, when in the second palette.
sin⁻¹ or sin^-1 |
Set the top of the stack to the inverse sine of the top of the stack, using the current angle mode |
cos⁻¹ or cos^-1 |
Set the top of the stack to the inverse cosine of the top of the stack, using the current angle mode |
tan⁻¹ or tan^-1 |
Set the top of the stack to the inverse tangent of the top of the stack, using the current angle mode |
sinh⁻¹ or sinh^-1 |
Set the top of the stack to the inverse hyperbolic sine of the top of the stack |
cosh⁻¹ or cosh^-1 |
Set the top of the stack to the inverse hyperbolic cosine of the top of the stack |
tanh⁻¹ or tanh^-1 |
Set the top of the stack to the inverse hyperbolic tangent of the top of the stack |
logᵧ or logy |
Pop x, pop y, push the logarithm base y of x. (Note that the unicode variant of this buttons is specified to have gamma instead of y for some reason) |
xʸ or x^y |
Pop x, pop y, push x to the power of y |
2ˣ or 2^x |
Pop x, push 2 to the power of x |
or log2 |
Pop x, push the logarithm base 2 of x |
Programmer
These buttons are available in programmer mode.
AND |
Pop X, pop Y, push the bitwise AND of X and Y |
OR |
Pop X, pop Y, push the bitwise OR of X and Y |
NOR |
Pop X, pop Y, push the bitwise NOR of X and Y |
XOR |
Pop X, pop Y, push the bitwise XOR of X and Y |
<< |
Pop X, push X nudged left by one bit. The lowest bit of the result is always zero |
>> |
Pop X, push X nudged right by one bit. The highest bit of the result is always zero |
X<<Y |
Pop Y, pop X, push X shifted left by Y bits. The lowest bits (shifted in) of the result are always zero |
X>>Y |
Pop Y, pop X, push X shifted right by Y bits. The highest bits (shifted out) of the result are always zero |
byte-flip |
Pop X, swap the pairwise bytes of X (0x0123456789abcdef turns into 0x23016745ab89efcd) and push |
word-flip |
Pop X, swap the pairwise words of X (0x0123456789abcdef turns into 0x45670123cdef89ab) and push |
RoL |
Pop X, push X rotated left by one bit (cycling) |
RoR |
Pop X, push X rotated right by one bit (cycling) |
2's |
Pop X, push the two's complement of X |
1's |
Pop X, push the one's complement of X |
Conversions
A conversion button is composed of two elements: The unit to convert from, a > character, and the unit to convert to. An example of a conversion button is Celsius>Fahrenheit
. Conversion buttons are available in basic and scientific modes. A conversion will pop x from the stack, then perform the conversion on x and push the result to the stack.
Only compatible units can be converted between. Below is a list of units available in each category:
Area
Acres |
|
Ares |
|
Decares |
|
Hectares |
|
Square-Centimeters |
Refers to square centimeters |
Square-Feet |
Refers to square feet |
Square-Kilometers |
Refers to square kilometers |
Square-Meters |
Refers to square meters |
Square-Miles |
Refers to square miles |
Square-Millimeters |
Refers to square millimeters |
Square-Yards |
Refers to square yards |
Energy or work
BTUs |
British thermal units |
Calories |
Food calories |
Ergs |
|
Foot-Pounds |
Foot pounds |
Joules |
|
Kilogram-Calories |
The other kind of calories |
Kilogram-Meters |
(???) |
Kilowatt-Hours |
Refers to kilowatt hours |
Newton-Meters |
It's the same as Joules |
Length
Centimeters |
|
Feet |
|
Inches |
|
Kilometers |
|
Meters |
|
Miles |
|
Millimeters |
|
Nautical-Miles |
Refers to nautical miles |
Yards |
Power
BTUs/Minute |
BTUs per minute |
Foot-Pounds/Minute |
Foot pounds per minute |
Foot-Pounds/Second |
Foot pounds per second |
Horsepower |
|
Kilowatts |
|
Watts |
Speed
Feet/Minute |
Feet per minute |
Feet/Second |
Feet per second |
Kilometers/Hour |
Kilometers per hour |
Kilometers/Minute |
Kilometers per minute |
Knots |
|
Meters/Second |
Meters per second |
Miles/Hour |
Miles per hour |
Miles/Minute |
Miles per minute |
Temperature
Celsius
|
Fahrenheit
|
Kelvin
|
Time
Seconds
|
Minutes
|
Hours
|
Days
|
Weeks
|
Years
|
Volume
Cubic-Feet |
Feet cubed |
Cubic-Meters |
Meters cubed |
Fluid-Drams(US) |
Fluid drams (US unit) |
Fluid-Ounces(US) |
Fluid ounces (US unit) |
Gallons(US) |
Gallons (US unit) |
Liters |
|
Pints(US) |
Pints (US unit) |
Quarts(US) |
Quarts (US unit) |
Weights and masses
Drams |
|
Grams |
|
Kilograms |
|
Long-Tons |
Long tons |
Ounces |
|
Pounds(US) |
Pounds (US unit) |
Short-Tons(US) |
Short tons (US unit) |
Slugs |
|
Tonnes |