Easyfuck

From Esolang
Jump to navigation Jump to search
easyfuck
Paradigm(s) imperative
Designed by Quadruplay
Appeared in 2024
Memory system Cell-based
Dimensions one-dimensional
Computational class Turing complete
Major implementations Original
Influenced by brainfuck
Extended Brainfuck
Brainfuck++++++++++++++++++++
Influenced none
File extension(s) .ef

Easyfuck is an esoteric programming language made to make programming in brainfuck much easier and more approachable. It includes better control flow, mathematical and bitwise operations, a storage cell, and most importantly functions.

Overview

Memory Management

Easyfuck operates on a right-infinite array of 8-bit cells, with the pointer indicating the current cell. Additionally, a separate 8-bit storage cell exists. The language provides commands for moving the pointer within the array:

Command Description
> Moves the pointer one cell to the right.
< Moves the pointer one cell to the left. If the pointer reaches below the 0th cell, it loops around to the furthest explored cell to the right.
J Moves the pointer back to the 0th cell.
U Unexplores the furthest explored cell to the right, setting it to 0, and moving it back to the unexplored state.
P Moves the pointer to the right by the value of the signed integer stored in the cell at the pointer. Negative values move the pointer left. All unexplored cells passed by the pointer get explored, and if the pointer reaches below the 0th cell, it loops around.

In Easyfuck, the concept of an explored cell refers to any cell previously visited by the pointer or one that holds a non-zero value.

Note: Unexploring a cell while pointing to it immediately explores it again.



Data Movement

Data manipulation in Easyfuck involves moving data around using the storage cell and three associated commands:

Command Description
$ Copies the contents of the cell at the pointer to the storage cell
! Copies the contents of the storage cell to the cell at the pointer
S Swaps the contents of the storage cell and the cell at the pointer



I/O Operations

Easyfuck supports conventional input and output operations through various commands:

Command Description
, Waits for a character and puts its Unicode value modulo 256 into the cell at the pointer.
. Outputs the Unicode character associated with the value stored in the cell at the pointer.
" Waits for a number from 0 to 255 and puts it into the cell at the pointer.
' Outputs the value stored in the cell at the pointer as an unsigned integer.
I Waits for a number from 0 to 65536 and puts it into the bi-cell at the pointer.
O Outputs the value stored in the bi-cell at the pointer as an unsigned integer.
R Clears the output.
L Clears a single line of the output.
Q Waits for a character and puts its Unicode value modulo 256 into the cell at the pointer. If a character is not received promptly, it defaults to 0. The waiting time is calculated in milliseconds by multiplying the value of the cell at the pointer by 10.
G Moves the output cursor to the column decided by the value in the cell to the left, and the row decided by the cell at the pointer.

In Easyfuck, a bi-cell refers to the cell at the pointer and the cell immediately to the left, acting together as a 16-bit number.

A command exists that modifies the output of ..

Command Description
H Switches the output of . to use a different table. Using it again switches it back to the default

The table below provides a more detailed representation:

Value Alt Character Default Character Value Alt Character Default Character Value Alt Character Default Character Value Alt Character Default Character
0 NUL 64 @ 128 PAD 192 À
1 SOH 65 A 129 HOP 193 Α Á
2 STX 66 B 130 BPH 194 Β Â
3 ETX 67 C 131 NBH 195 Γ Ã
4 EOT 68 D 132 IND 196 Δ Ä
5 ENQ 69 E 133 NEL 197 Ε Å
6 ACK 70 F 134 SSA 198 Ζ Æ
7 BEL 71 G 135 ESA 199 Η Ç
8 BS 72 H 136 HTS 200 Θ È
9 TAB 73 I 137 HTJ 201 Ι É
10 LF 74 J 138 LTS 202 Κ Ê
11 VT 75 K 139 PLD 203 Λ Ë
12 FF 76 L 140 PLU 204 Μ Ì
13 CR 77 M 141 RI 205 Ν Í
14 SO 78 N 142 SS2 206 Ξ Î
15 SI 79 O 143 SS3 207 Ο Ï
16 DLE 80 P 144 DCS 208 Π Ð
17 DC1 81 Q 145 PU1 209 Ρ Ñ
18 DC2 82 R 146 PU2 210 Σ Ò
19 DC3 83 S 147 STS 211 Τ Ó
20 DC4 84 T 148 CCH 212 Υ Ô
21 NAK 85 U 149 MW 213 Φ Õ
22 SYN 86 V 150 SPA 214 Χ Ö
23 ETB 87 W 151 EPA 215 Ψ ×
24 CAN 88 X 152 SOS 216 Ω Ø
25 EM 89 Y 153 SGCI 217 α Ù
26 SUB 90 Z 154 SCI 218 β Ú
27 ESC 91 [ 155 CSI 219 γ Û
28 FS 92 \ 156 ST 220 δ Ü
29 GS 93 ] 157 OSC 221 ε Ý
30 RS 94 ^ 158 PM 222 ζ Þ
31 US 95 _ 159 APC 223 η ß
32 Space 96 ` 160 NBSP 224 θ à
33 ! 97 a 161 ¡ 225 ι á
34 " 98 b 162 ¢ 226 κ â
35 # 99 c 163 £ 227 λ ã
36 $ 100 d 164 ¤ 228 μ ä
37 % 101 e 165 ¥ 229 ν å
38 & 102 f 166 ¦ 230 ξ æ
39 ' 103 g 167 § 231 ο ç
40 ( 104 h 168 ¨ 232 π è
41 ) 105 i 169 © 233 ρ é
42 * 106 j 170 ª 234 ς ê
43 + 107 k 171 « 235 σ ë
44 , 108 l 172 𐕣 ¬ 236 τ ì
45 - 109 m 173 ­SHY 237 υ í
46 . 110 n 174 ® 238 φ î
47 / 111 o 175 🕭 ¯ 239 χ ï
48 0 112 p 176 🕮 ° 240 ψ ð
49 1 113 q 177 🕱 ± 241 ω ñ
50 2 114 r 178 🕾 ² 242 ò
51 3 115 s 179 🖂 ³ 243 𓁌 ó
52 4 116 t 180 🗲 ´ 244 𓃒 ô
53 5 117 u 181 µ 245 𓃗 õ
54 6 118 v 182 246 𓃩 ö
55 7 119 w 183 🗿 · 247 𓅃 ÷
56 8 120 x 184 ¸ 248 𓆈 ø
57 9 121 y 185 ¹ 249 𓆌 ù
58 : 122 z 186 º 250 𓆉 ú
59 ; 123 { 187 » 251 𓆏 û
60 < 124 | 188 ¼ 252 𓆙 ü
61 = 125 } 189 ½ 253 𓆟 ý
62 > 126 ~ 190 ¾ 254 𓆤 þ
63 ? 127 DEL 191 ¿ 255 𓆣 ÿ



Additional Output Commands

Two additional commands exist for producing output:

Command Description
T Produces a sound with the tone defined by the cell at the pointer and length defined by the cell to the right. This operation does not pause the program.
K Changes the color of the characters produced henceforth.

The color produced by the K command is derived from the value of the byte at the pointer and is encoded as follows:

Bit(s) Function
128 Toggles blinking on and off
64 Toggles underline on and off
32, 16 Red
8, 4 Green
2, 1 Blue



Arithmetic Operations

Arithmetic operations enable mathematical computations within Easyfuck programs:

Command Description
+ Increments the cell at the pointer.
- Decrements the cell at the pointer.
= Adds the value of the storage cell to the value in the cell at the pointer, and stores the result in the cell at the pointer.
_ Subtracts the value of the storage cell from the value in the cell at the pointer, and stores the result in the cell at the pointer.
* Multiplies the value in the cell at the pointer by the value of the storage cell, and stores the result in the cell at the pointer.
M Multiplies the value of the bi-cell at the pointer by the value of the storage cell, and stores the result in the bi-cell at the pointer.
/ Divides the value in the cell at the pointer by the value of the storage cell, and stores the quotient in the cell at the pointer.
N Divides the value of the bi-cell at the pointer by the value of the storage cell, and stores the quotient in the bi-cell at the pointer.
\ Calculates the square root of the value in the cell at the pointer, and stores the result in the cell at the pointer.
V Calculates the square root of the value of the bi-cell at the pointer, and stores the result in the bi-cell at the pointer.
% Computes the remainder of dividing the value in the cell at the pointer by the value of the storage cell, and stores the result in the cell at the pointer.
: Finds the maximum value between the cell at the pointer and the storage cell, and stores the result in the cell at the pointer.

Division by 0 is handled by assuming a cut-off 9-bit divisor: 0b100000000, effectively dividing by 256.

To simplify number generation, Easyfuck introduces hexadecimal commands:

Command Description
0-9 A-F Sets the value of the cell at the pointer to the corresponding hexadecimal value multiplied by 16.



Bitwise Operations

For precise data manipulation, Easyfuck provides bitwise operations:

Command Description
{ Performs a left logical shift on the value of the cell at the pointer.
} Performs a right logical shift on the value of the cell at the pointer.
~ Performs a bitwise NOT on the value of the cell at the pointer.
| Performs a bitwise OR between the value of the cell at the pointer and the value of the storage cell, storing the result in the cell at the pointer.
& Performs a bitwise AND between the value of the cell at the pointer and the value of the storage cell, storing the result in the cell at the pointer.
^ Performs a bitwise XOR between the value of the cell at the pointer and the value of the storage cell, storing the result in the cell at the pointer.
Y Reverses the order of bits of the value in the cell at the pointer.



Functions

Functions in Easyfuck can only be assigned to lowercase letters, following this syntax:

f(++++)

The code snippet above assigns the function f to execute the instructions ++++. Once assigned, f will execute ++++ whenever invoked. Functions can be freely reassigned.



Control Flow

Before discussing control flow commands, let's address miscellaneous commands:

Command Description
# Initiates a comment that ends on a new line
W Suspends program execution for a duration specified by the value of the cell at the pointer, multiplied by 10 milliseconds
Z Sets the value of the bi-cell at the pointer to the number of seconds elapsed since the start of the program
? Assigns a random value between 0 and 255 to the cell at the pointer

In Easyfuck, two primary control flow structures exist:

  • While Loops
  • Conditional Statements

While loops are constructed using the following commands:

Command Description
[ Initiates a while loop
] Terminates a while loop

While loops in Easyfuck lack explicit conditional statements. Instead, they continue execution as long as the value of the cell at the pointer evaluates to true.

Crude conditional statements can be formed using while loops, as shown in the following example:

[                   # Start of loop A
    f               # Some code represented by function f
    0
]                   # End of loop A

In this example, if the byte at the pointer is true, execution enters the loop, executes some code, resets the cell at the pointer, and exits the loop. This method overwrites a cell, which, while not problematic, may require additional steps such as replacing 0] with S0]S or copying the cell elsewhere. To address this, breaks have been introduced:

Command Description
; Exits the innermost while loop; if not within one, acts as @
@ Exits the innermost function; if not within one, acts as X
X Terminates the program

This allows conditional statements to avoid interference with stored data when rewritten, such as:

[f;]

However, more complex conditions can be created, as demonstrated in the next section.

Conditional Statements are best achieved using the ` command:

Command Description
` Skips the next command unless the previous command sets the overflow flag

Notably, chaining two ` commands skips the subsequent command only if the one before them set the overflow flag. Below is a table of commands that set the overflow flag and their requirements:

Command Sets the flag when:
> Moving the pointer to an unexplored cell
< Looping the pointer around
U Pointing to an unexplored cell, thus exploring it immediately
P Looping the pointer around or exploring new cells
+ Overflowing the cell at the pointer
- Underflowing the cell at the pointer
= Overflowing the cell at the pointer
_ Underflowing the cell at the pointer
* Overflowing the cell at the pointer
M Overflowing the bi-cell at the pointer
} The lost bit is a 1
{ The lost bit is a 1



Lambdas

Lambdas in Easyfuck are functions that are not assigned to a variable and are executed immediately. They are primarily used when you want to skip multiple commands or break out of several nested while loops.

Consider the following example:

[ code [ more code [ still more code ; ] even more code ] code. again ]

In this example, the ; command will break only out of the innermost loop. To break out of all nested loops, you can enclose them within a lambda and use @ to break out of it:

( [ code [ more code [ still more code @ ] even more code ] code. again ] )

Another use for lambdas is to skip multiple commands. For instance:

code `(lambda code)

Initializer Data

If you've followed all the steps so far and tried writing a program yourself, you might have encountered an issue when including the @ symbol. This is because, aside from breaking from functions, @ is also used to mark the end of the code.

For example:

f('>$<!>>$<!<$>>=`@>.<<<f)>+>+>2<<<f>.<<<'2.>'

will be executed as:

f('>$<!>>$<!<$>>=`@

What happens to the rest of the code? It is used to initialize the array, setting it to:

>.<<<f)>+>+>2<<<f>.<<<'2.>'

In order to execute everything normally, another @ is needed at the end of the code:

f('>$<!>>$<!<$>>=`@>.<<<f)>+>+>2<<<f>.<<<'2.>'@

Example programs

Hello World

[.>]@Hello World!

Fibonacci generator

a(<+`X>)b(=`a)l(<<)r(>>)    #helper functions
f(r$l!>$l!>rr$l!>$l!>rll<$rr=`X>ll$rrbOr.lllf)  #recursive generating-printing function
[.>]1----.0>O2.0r+O2.0+r+O2.0+r2lllf    #initializer data printer, and fibonacci data pregen
@Fibonacci:

Prime generator

#Array structure:
#cell           space character
#bi-cell        checked number
#bi-cell        copy of checked number (for checking)
#bi-cell        copy of checked number (for comparisons)
#bi-cell        sqrt of checked number (for optimization)

a(<+`X>)i(+`a)  #defining a bi-cell incrementing function i
b(<->)d(-`b)    #defining a bi-cell decrementing function d
r(<$>>!<$>>!)   #defining a function r that copies the current bi-cell to the bi-cell to the right and moves the pointer to it
f(J>>)          #defining a function f that goes back to the first bi-cell
p(fO<<.>>)      #defining a function p that prints the first bi-cell and a space
c(<<<$>>^<$>>^) #defining function c that turns a bi-cell to zero if the bi-cell to the left is the same

[.>]J[U]        #printing and clearing memory
1------.2       #printing new line and setting first cell to a space character
>>iipip         #printing first 2 primes

l(
    fiirrrV     #increment number twice (primes other than 2 are odd) and initialize the other bi-cells
    $<<NM       #divide and multiply 3rd bi-cell by 4th
    c<$>=       #compare with 2nd to check if 3rd mod 4th is 0, afterwards collapse to single cell
    -`@0+       #if 0 break, else set to 1
    frr>>-      #copy 1st to 2nd and 3rd again, then decrement 4th
    -[+         #if 4th is one, skip while loop
    $<<NM       #repeat the steps from before
    c<$>=
    -`@0+
    frr>>-
    -]
    p           #print the number
)
[llfii]        #loop the checking function, incrementing 1st bi-cell twice every second run to target only number of form 6k+1 and 6k+5

#initializer data:
@Primes:

D6 roller:

#Array structure:
#cell           number of dice
#cell           6 (faces)
#cell           145 (die character)
#cell           random
#bi-cell        sum

[.0>]J              #print and reset initialized data
>1------.<          #print new line
"'>.0++++++>9+H     #put user input into cell 0, put 6 into cell 1 and storage, put 145 into cell 2, switch to game typeset
a(=`(<+>))          #define function a that adds storage to bi-cell at pointer
J[
    ->$>>?%$        #decrement cell 0 and generate random number 0-5
    <=._>+$>>       #print the correct die and increase random variable to 1-6
    a               #add rolled value to total sum
J]
1------H.           #print new line
>>>>>O              #print total sum
@Give number of dice:

Further Reading

The Official Course