Instantly share code, notes, and snippets.

AMiller42/Vim Unshackled Explanation.md Secret

Last active January 27, 2024 03:52
Show Gist options
• Save AMiller42/96daeb2ccf32f88cc0df212a5dba59b8 to your computer and use it in GitHub Desktop.

💎

All explanations created with the help of Luminespire.

Helper Functions

These macros are needed for various common functions performed by other functions.

Macro: @f - Convert From Trinary
Changes a memory cell from, e.g. "m0 0 22" to "m0 0 8", and leaves the original value in @x

^WWD                                                                            # ‎⁡Delete the current memory value into @- and @"
:let@x=@-                                                                   # ‎⁢Set @x equal to @-
|let@"=                                                            # ‎⁣Set @" equal to:
map(split(@",'\zs'),                           )       # ‎  For each trit x in @":
map(               ,{a,b->           pow(3,a) })       ‎⁢⁡    Index of x raised to the power of 3...
map(               ,{a,b->  float2nr(        )})       ‎⁢⁢    cast to int...
map(               ,{a,b->b*                  })       ‎⁢⁣    multiplied by x
join(                                                ,'+')  ‎⁢⁤    Joined by '+'
# ‎⁣⁡Now @" is a string of the form x3^0 + x3^1 + x3^2 + x3^3...
"=<C-R>"                                                                        # ‎⁣⁢Execute @" as an expression
p                                                                               # ‎⁣⁣Paste the result
Macro: @t - Convert To Trinary
Changes a memory cell from, e.g. "m0 0 8" to "m 0 0 22"

^WWD                      # ‎⁡Delete the current memory value into @"
:wh@">2               # ‎⁢While the number in @" is greater than 2:
norm"=<C-V><C-R>"%3<C-V>  # ‎⁣  Modulo @" by 3 to get the next trit,
p                         # ‎⁤  Paste the trit
endw                      # ‎⁢⁢End while
p                         # ‎⁢⁣Paste the final trit
Macro: @w - Get Value w/o Repeated Digits
Sets register @- to the currently selected memory value, deduplicating the highest trit

^WxP                       # ‎⁡Copy most significant trit (MST) into @-
Wy\$                    # ‎⁢Copy memory value into @0
:s/<C-R>-*\$         # ‎⁣Trim all of MST from the end of the value...
/<C-R>-  ‎⁤  and replace them with a single MST
^WWD                       # ‎⁢⁡Delete the modified value into @-
"0p                    # ‎⁢⁢Replace the original value
Macro: @v - Increment
Increments the current memory value

@f@t@f                                  # ‎⁡Convert value from, to, from trinary (This is necessary so to remove leading 0s from the trinary value)
<C-A>@t                           # ‎⁢Increment number and convert back to trinary
^WWy\$                      # ‎⁣Copy memory value to @"
:if len(@0)!=len(@x)  # ‎⁤If the incremented number is longer than the original:
norm\$x^Wx"=@-%2<C-V>                    # ‎⁢⁡  Increment the most significant trit,
P
\$"=(@-+1)%3<C-V>                       # ‎⁢⁢  Carry the trit
p
en                                      # ‎⁢⁣End if
Macro: @g - Get Memory Value
Move cursor to the cell pointed to by the current value. Sets @" to the new value, and @- to the new value, from trinary

mg                                 # ‎⁡Place a marker `g at the current cell
@w                               # ‎⁢Copy deduplicated memory value to @-
gg/m<C-R>- \|m!                # ‎⁣Find cell pointed to by @- if it exists, or cell '!'
WWy\$                               # ‎⁤Copy memory value to @"
:let@s=@-                      # ‎⁢⁡Copy @- to @s for later use
|if@"==-1             # ‎⁢⁢If at cell '!' (value is -1):
# ‎⁢⁣Initialize new memory cell:
norm`g                             # ‎⁢⁤  Jump back to `g
^WxP                         # ‎⁣⁡  Copy most significant trit (MST) to @-
Wyll                     # ‎⁣⁢  Copy least significant trit to @"
let@x=4*@-+@"+6-@-                 # ‎⁣⁣  Set @x to (4 * @-) + @" + 6 - @-
norm y\$                            # ‎⁣⁤  Copy remaining trits of value to @"
for_ in split(@",'\zs')            # ‎⁤⁡  For each trit _ in @":
let@x=(@x+3*(_+6-@-))%6            # ‎⁤⁢    Set @x to (@x + (3 * (_ + 6 - @-))) % 6
endfo                              # ‎⁤⁣  End for
let@x=@x+1                         # ‎⁤⁤  Increment @x
norm`n@xjy\$                        # ‎⁢⁡⁡  Copy initial_values[@x - 1] to @"
2Gom<C-R>s              # ‎⁢⁡⁢  Initialize cell @s...
<C-V><C-R>"  ‎⁢⁡⁣    with value @"
en                                 # ‎⁢⁡⁤End if
# ‎⁢⁢⁡End cell initialization. Whether or not initialization was needed, the cursor is now at the desired cell.
@f^WWD                             # ‎⁢⁢⁢Convert value from trinary, save to @x
"xp                          # ‎⁢⁢⁣Restore original value
:let@"=@x                 # ‎⁢⁢⁤Set @" equal to @x
Macro: @o - Crazy Operation
Uses @n and @m to do opr(@n, @m), saves result to @m (opr formula taken from https://codegolf.stackexchange.com/a/167684/101522)

:let@"=len(@n)-len(@m)                                                                   # ‎⁡Set @" equal to len(@n) - len(@m)
|if@">0                                                            # ‎⁢If @n is longer than @m:
let@m=@m.repeat(@m[len(@m)-1],@")                                                        # ‎⁣  Pad @m with @m[-1] to the length of @n
elsei@"<0                                                                                # ‎⁤Else if @m is longer than @n:
let@n=@n.repeat(@n[len(@n)-1],-@")                                                       # ‎⁢⁡  Pad @n with @n[-1] to the length of @m
en                                                                                       # ‎⁢⁢End if
|let@m=                                                                                # ‎⁢⁣Set @m equal to:
join(                                                                     ,'')  # ‎⁢⁤  Concatenation of:
map(split(@n,'\zs'),                                                )      # ‎⁣⁡    Each trit x in @n:
map(               ,{a,b->               b+(@m[a]*512)+8           })      ‎⁣⁢        x + (@m[index of x] * 512) + 8...
map(               ,{a,b->           pow(               ,2)        })      ‎⁣⁣        squared...
map(               ,{a,b->  float2nr(                      )       })      ‎⁣⁤        cast to int...
map(               ,{a,b-> (                                %82)           ‎⁤⁡        modulo by 82...
map(               ,{a,b->(                                     %3)})      ‎⁤⁢        modulo by 3
Macro: @e - Command Encipher
Translate (C) using the lookup table if 32 < (C) < 127

/rc                                # ‎⁡Jump to (C) copying the base10 to @-
@g
^Wyl:if@"<1                      # ‎⁢If most significant trit (MST) of (C) is 0:
let@"=@-                           # ‎⁣  Set @" equal to @-
en                                 # ‎⁤End if
|if@">32&&@"<127                 # ‎⁢⁡If 32 < @" < 127:
let@"=nr2char(@")                  # ‎⁢⁢  Cast @" to char
if@"=="/"                          # ‎⁢⁣  If @" is '/' (breaks regexes):
let@"='\/'                         # ‎⁢⁤    Escape @"
en                                 # ‎⁣⁡  End if
norm`x                             # ‎⁣⁢  Jump to lookup table
/\V<C-V><C-R>"<C-V>          # ‎⁣⁣  Jump to @" in lookup table
j"zyl                              # ‎⁣⁤  Copy lookup value to @z
@g
^WWC                   @z        # ‎⁤⁢  Replace (C) with @z...
<C-V><ESC>
<C-V><C-R>=char2nr(@z)<C-V>  ‎⁤⁣    cast to int
@t                       # ‎⁤⁤  Convert to trinary
en                                 # ‎⁢⁡⁡End if
Macro: @u - Update Rotwidth
Increases rotwidth by 5 if len(D) > rotwidth/2

/rd                    # ‎⁡Save deduplicated register D to @-
@w
+Wy\$                 # ‎⁢Copy current rotwidth to @"
:if@0/2<len(@-)  # ‎⁣If len(@-) is more than half the current rotwidth:
let@0=@0+5             # ‎⁤  Increase rotwidth by 5
norm^WD"0p             # ‎⁢⁡  Save new rotwidth
Macro: @h - Get Command
Saves the number for the next command to @z, i.e. (C + (C)) % 94

@f^WWD               # ‎⁢Convert from trinary and copy to @-
"xp            # ‎⁣Restore original value
:let@z=@-   # ‎⁤Save @- to @z for later use
@g                   # ‎⁢⁡Copy (C) to @-
:let@z=(@-+@z)%94  # ‎⁢⁢Set @z to (@- + @z) % 94
Macro: @d - Read Command
Copy the next character of the program into memory and convert to trinary (assumes only valid programs)

gg"zx                                   # ‎⁡Delete next char of program into @z
^WWD"=_                                 # ‎⁣Replace register A with variable _ (variable set by outer for loop)
p
@t@w                                   # ‎⁤Copy deduplicated trinary form to @-
ggjom<C-R>-                        # ‎⁢⁡Create new memory cell with address @-...
0               @z     # ‎⁢⁢and set initial value to @z...
<C-R>=char2nr(@z,1)  # ‎⁢⁣cast to int...
<ESC>@t                                 # ‎⁢⁤converted to trinary

Commands

These are the macros for the actual Malbolge Unshackled commands.

Note: Commands v (hlt) and o (NOP) don't need a macro.
Macro: @i
Command: i (jmp)

/rd        # ‎⁡Copy (D) to @0
@g^Wy\$
/rc  # ‎⁢Replace register C with @0
WD"0p
Macro: @a
Command: < (out)

@f                                         # ‎⁢Convert from trinary
^Wyl                                     # ‎⁣Copy most significant trit (MST) to @0
WD                                   # ‎⁤Move value to @-
"xp                                # ‎⁢⁡Restore original value
`o<DEL>                         # ‎⁢⁢Jump to end of output
:if@0.@-[len(@-)-1]==21  # ‎⁢⁣If highest trits are 21:
norm o                                     # ‎⁢⁤  Print newline to output
el                                         # ‎⁣⁡Else:
norm A              @-                     # ‎⁣⁢  Print @- to end of output...
<C-R>=nr2char(@-,1)                  # ‎⁣⁣  cast to char
en                                         # ‎⁣⁤End if
Macro: @b
Command: / (in)

`i+x                  # ‎⁡Move next char of input to @-
Wr0                   # ‎⁣Replace most significant trit (MST) with 0
WD"=        @-     # ‎⁤Replace value with @-...
p
"=char2nr(@-,1)  # ‎⁢⁡cast to int
@t                   # ‎⁢⁢Convert to trinary
Macro: @c
Command: * (rot)

/rw                                # ‎⁡Copy current rotwidth to @y
W"yy\$
^W"xyl                     # ‎⁣Copy most significant trit (MST) to @x
Wy\$                  # ‎⁤Copy value to @"
:if@y>len(@")     # ‎⁢⁡If @" is shorter than the rotwidth:
norm A<C-R>=repeat(@x,@y-len(@"))  # ‎⁢⁢  Pad @" to rotwidth using MST
en                                 # ‎⁢⁣End if
^WWx                               # ‎⁢⁤Delete least significant trit (LST) of value...
\$p                             ‎⁣⁡  and rotate it to the top
^Wy\$                         # ‎⁣⁢Copy value with MST to @0
/ra                      # ‎⁣⁣Replace register A with @0
WD"0p
Macro: @j
Command: j (movd)

@g
^Wy\$     # ‎⁢Copy value to @0
WD"0p      # ‎⁤Replace the value with @0
@u    # ‎⁢⁡Update rotwidth
Macro: @p
Command: p (opr)

Wyl\$p                                                       # ‎⁢Copy most significant trit (MST) to the top of the value
^WW"ny\$                                                # ‎⁣Copy value to @n
^Wyl\$p                                      # ‎⁢⁡Copy MST to the top of the value
^WW"my\$                               # ‎⁢⁢Copy value to @m
@o                             # ‎⁢⁣Run the crazy op
^WWD"mp                      # ‎⁢⁤Replace value with result
x^WR<C-R>"<ESC>       # ‎⁣⁡Move top trit back to MST
y\$     # ‎⁣⁢Copy final value to @0
WD"0p                                                       # ‎⁣⁤Replace value with @0

Memory Initialization

Most of the initialization is simply typing characters in different places, so here's the parts that are of note.

# Set marker `x, then print the printable ASCII codepage
mx:for_ in range(32,126)
norm A<C-V><C-R>=nr2char(_)<C-V>
endfo

# Call macro @d for each character in the program
:for_ in range(len(@x))
norm @d
endfo

# Too tired to explain properly, but this extrapolates the 6 default cell values from the existing memory, and stores it after the `n marker
/m<C-R>"
^W"zD"zpj^Wy\$`no<ESC>"0p^2x\$pxo<ESC>"zp^2x\$px:norm<C-R>=repeat("-\"my\$+\"ny\$@oo<C-V><ESC>\"mp",18-((len(@x)%6)))
G5-d`nO%<ESC>mnj:g/^\d/norm\$x^Pa

Main Execution Loop

:wh1             # ‎⁡While true:
norm@h           # ‎⁢  Get next command, stored in @z
if@z             # ‎⁣  Command check:
norm@i           # ‎⁤    If command 4: Run @i (jmp)
norm@a           # ‎⁢⁡    If command 5: Run @a (out)
norm@b           # ‎⁢⁢    If command 23: Run @b (in)
norm@c           # ‎⁢⁣    If command 39: Run @c (rot)
norm@j           # ‎⁢⁤    If command 40: Run @j (movd)
norm@p           # ‎⁣⁡    If command 62: Run @p (opr)
brea             # ‎⁣⁢    If command 81: Break the loop (hlt)
en               # ‎⁣⁣  End if (All other command numbers are NOP)
norm @e          # ‎⁣⁤  Encipher (C)
/rc<C-V>  # ‎⁤⁡  Increment register C
@v
j@v            # ‎⁤⁢  Increment register D
endw             # ‎⁤⁣End while
to join this conversation on GitHub. Already have an account? Sign in to comment