Letterfuck

From Esolang
Jump to navigation Jump to search

Letterfuck

Letterfuck (LF) is an esoteric programming language inspired by Brainfuck and Piet, but using letters as commands. LF combines a memory tray similar to Brainfuck with a stack like Piet. Programs are sequences of letters, with the differences between letters encoding commands and repeated letters forming blocks.

Overview

LF programs use a memory tray (array of cells) and a stack (LIFO). Each command is represented by the change in letters.
- Syntax (bytecode): aAbB

  • a is a parameter for the current command
  • b is a parameter for the next command
  • A,B are letters from A-Z

- Opcode = index(B) - index(A) if B > A, or 26 + index(B) - index(A) if B < A. - Repeated letters form a block, with size representing the parameter for some commands. - Example: AAAB does command 1, parameter 3

Commands

Opcode Command Param Description
1 IDXINC VAL Increase memory index: index += VAL
2 IDXDEC VAL Decrease memory index: index -= VAL
3 INC VAL Add VAL to current cell: tray[index] += VAL
4 DEC VAL Subtract VAL from current cell: tray[index] -= VAL
5 IN(CHAR) NONE Input a character: tray[index] = ASCII(input_char())
6 ZERO (ZZ) NONE Next command receives 0 as parameter. If its block size is above 1, use ZZ (zero-zero) as a parameter instead
7 IN(NUM) NONE Input a number: tray[index] = input_number()
8 OUT(CHAR) CELL Output ASCII character: system.write(tray[index])
9 OUT(NUM) CELL Output number: system.write(tray[index])
10 NEG VAL Negation: NEG a = -a; if a=ZZ → 1
11 STARTLOOP VAL Loop VAL times
12 ENDLOOP NONE End loop
13 EQ VAL Compare top of stack with VAL: 1 if equal, -1 if not
14 BRK NONE Break loop
15 WHILE VAL While VAL=1, repeat loop
16 ENDWHILE NONE End while loop
17 PUSH CELL Push cell to stack, reset cell. If it was used with param ZZ, do not reset cell
18 POP STACK Pop stack to cell. If it was used with param ZZ, turn to PEEK (pastes the top of stack to cell without removing it from stack)
19 CMP STACK Compare top two stack values (Top vs Second). Returns 0 if Top<Second, 1 if Top>Second, 2 if Top=Second
20 DUP STACK Duplicate top of stack
21 SUB STACK Pops Top and Second, subtract them (Top-Second), pushes the result back
22 ADD STACK Pops Top and Second, add them (Top+Second), pushes the result back
23 MUL STACK Pops Top and Second, multiply them (Top*Second), pushes the result back
24 DIV STACK Pops Top and Second, divide and them and round the result (Top//Second), pushes the result back
25 END NONE End program

LFSP and LFASM

LF is hard to read, so two helper syntaxes exist:

  • LFSP (LF-Simplified): compresses repeated letters. Example:

AAAAAAAAALLLLLLLLOAIH → 9A8LOAIH

  • LFASM (LF Assembly): easier coding:

9A8LOAIH →

STARTLOOP, 9 // 9A8L
INC, 8       // 8LO
ENDLOOP      // OA
OUT(CHAR)    // AI
END          // IH

LF-High (LFH)

LF-High is an advanced version of LF with major improvements:

  • Compact commands:
    • in, form, dest (opcode 5)
    • out, form, target, start, end (opcode 8)
    • idx, val (val can be negative) (opcode 1)
    • inc, val, ... (val can be negative, supports increasing multiple cells at once) (opcode 3)
  • New commands (to fill in the spot of: IDXDEC, DEC, IN(NUM), OUT(NUM)):
    • mov, pt, val (opcode 2)
    • sel, target (opcode 4)
  • Syntax expansion:
    • cmp, val1, val2, dest
    • add, val1, val2, val3,..., dest
    • sub, va11, val2, val3,..., dest = val1-val2-val3-...
    • div, val1, val2, val3,..., dest = (((...((val1//val2)//val3)//val4)...)))
  • Zone support with flags:
    • ^ → start zone
    • !! → end zone
    • # → zone pointer
    • $ → get self (see below)
    • ! → end param (see below)
  • Advanced stack operations, select stack, arithmetic on stack and cell. Local pointers for zones, and stack pointer (sp).

Example that includes some of the new commands

inc, ^4                    // start zone and makes the first value 4
sel, $                   // select current cell
idx, 2
inc, !!9
sel, $
add                      // adds the 2 selected cells, pushes them onto the stack
out, num, sp             // outs 13
end

Output: 13

  • $ references to a unit, depending on the suffix:
    • $c: current cell
    • $z: current zone
    • $n with n being a number: cell index n
    • $pt: the zone that contains local pointer pt
  • # references to the index of a unit:
    • #c: current cell index
    • Note:
      • # alone as a param for inc will create a zone pointer.
      • $#c = $c
  • % references to the size of a unit:
    • %c: get the current cell's "size". In fact, %c=1∀c
    • %z: get the current zone's size
    • %pt: get the size of the zone that contains local pointer pt
  • ! explanation:
    • Say we have the command sub, add, 5, 3, 2. Is it (5+3)-2 or 5+3+2-0? We can't know becasue both takes many params.
    • ! solves the problem: sub, add, 5, 3!, 2 = (5+3)-2; sub, add, 5!, 3, 2 = 5-3-2.

Mechanics of LF-High

Pointer focus: The cell that the last pointer that was moved points to will be the target for inc. To change focus without moving pointer, do idx, 0 or mov, pt, 0.

Notes

  • add, sub, mul, div returns a literal when in $(...) but pushes the literal onto the stack when not in $(...)

Advantages and disadvantages

  • Advantages: Very powerful; supports self-replicating code, complex stack operations, and zones.
  • Disadvantages: Difficult to read and debug, requires hard thinking and wise coding.

LF/LFH Programs

If any of you understands LF syntax, you can try writing a program here! I'd apperciate it, and even more if you manage to write a compiler for this thing.

Hello World!

out, char, "Hello World!"
end

LF: A"Hello World!"AIH

MOD

out, char, "Enter the diviend:"   //out, char with literal string as param wont modify the tape
in, num, #c                  //diviend here
inc, ^
out, char, "Enter the divisor:"
in, num, add, #c, 1          //divisor here
inc, !!, add, #c, 3          //inc stops when it encounters a destination
push, $c, zz
inc, #, pt1
mov, pt1, 2
inc, -1
while, 1
inc, 1
mul, $c, $(sub, #c, 1)
cmp
sloop, neg, eq, 0           //sloop = start loop
brk
eloop
mov, pt1, -2
push, $c, zz
mov, pt1, 2
ewhile
sloop, eq, 1
inc, -1
mul, $c, $(sub, #c, 1)
sub
pop
mul, $c, -1
out, num
end
sloop, eq, 2
out, num
endloop
end

See also