Skip to content

Instantly share code, notes, and snippets.

@gfixler
Last active September 26, 2023 08:22
Show Gist options
  • Save gfixler/f6073ebb59e1f488f8a6cef51a25310b to your computer and use it in GitHub Desktop.
Save gfixler/f6073ebb59e1f488f8a6cef51a25310b to your computer and use it in GitHub Desktop.
+++++ + ++++ + +++++++ ++
*+++++ + + ++++++++++++* + +++ +++++
++ + + + +++++*+++ + ++ + +++
+ + + + + + ++ + *++
+ + ++ + ++ +++ + ++
++ ++ * +++ ++ +++ + .+
++ ++ ++ ++ *++ .-- - --
---- -- -- -- -*- --- - --
- --- -- -- -- --* --- - --
-- -- -- -- -- --- *--------
-- -- -- -- -- -* -- - -.
+++ + + ++ + + + + + ++
*++ + +++ + +++ + +++++ ++
+*++++ +++++++ + +++++++*+ + ++++ ++ +
+++ +++ + +++*+ + ++ +.
- -
-- --
---- - --*-- --- -- ----- --
- ----*-------- ------ - -- --*-- ------ ----
- ------*-- -- - - -- - --- -. + + +++
* + + + + + ++ +++ + + + +++
++ + *+ + + + + ++ + + ++
+ +++ ++ ++ * + ++ ++ ++ ++
++ ++ ++ ++ + + *+ ++ .- --
-- -- -- ---- - -* ---- -- -
-- -- -- -- --- - *- - --- -- -
-- -- -- -- -- -*------- -- ---.+++
++ +* + ++ ++ + ++ ++ ++++++
++ + * + ++ + ++ ++ ++
+++ + ++++ +*+ +++++ ++ ++ ++
+++++++ * ++++ ++ + ++++ ++ + ++ ++
+*+ + .- - . -- -- -- -- --
- - --- - -
.+ ++ +++ +
++++++
++.`
_____________________________________________________________________________
">
_____________________________________________________________________________
t: 0
hom /^hom
mem gg:/^@c
nex @mjyiW@"
prv @mkyiW@"
inc @mWx01
dec @mWx24
bef @mO@c 0x27j0lruk
unu 0lr-@mlru/^@- lrc
aft @mo@c 0x27k0lruj
out @mWy$gg/^? @"lyl/^"> :noh $px27
stp `myl@rmm@h/\M^x18=@" Wy$@"`m
reg /[][><+-.,`]
clr :g/^@u/d @mWC0x27@o0WDGY@":noh
tap 0
> @n
< @p
+ @i
- @d
[
]
,
. @o
` :the end
????????btl??c?????????????????? !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
@b
@c 0
@a
" h go to the instructions
" n next memory address
" p previous memory address
" i increment current memory address
" d decrement current memory address
" b add memory address before current one
" u
" a add memory address after current one
" o output char at current memory address
" s step through current input instruction
" r increment current input instruction pointer
" c clear memory and reset all pointers
ggmm/^hom w"hyg_j"myg_j"nyg_j"pyg_j"iyg_j"dyg_j"byg_j"uyg_j"ayg_j"oyg_j"syg_j"ryg_j"cyg_:noh
@gfixler
Copy link
Author

gfixler commented Feb 6, 2018

The above is [almost] a BF interpreter (just missing the bracket and comma commands), which runs in Vim entirely via the Vim macro system, and which I created in mid to late 2012. The fancy message at the top is a sample program.

To use this, open it in Vim, hit G to go to the bottom line, yg_ to copy it into the default register, then @" to run the default register. This will cause Vim to visit each of the command lines (hom, mem, nex, etc.), copying each into its particular register (note: you can view all registers by typing :reg, followed by enter). With that done, you can run the program. Here, the sample program is the "IT'S A TRAP" text at the top, created with figlet, and replaced by the BF program I wrote using—what else?—a Vim macro, and with a few * characters evenly spaced throughout to pad it out to fit perfectly, as there were a few more characters in the large, script, figlet characters.

To run the program, type 641@s, and sit back; it'll take a while, and it will slowly print "it's a trap" in the output area (just below the program). The magic number 641 is simply the count of characters in the program, and the @s is the macro, stored in register s, that steps through a single command character in the program. You can of course use a smaller count to step fewer times, or just keep doing @s to step manually, one command at a time.

Make sure your programs end with a ` (grave accent, aka 'backtick'). This meta command causes the interpreter to try to run a Vim command "the end", which doesn't exist, which crashes out of the macro playback, so even if you do 10000@s, to step the program 10k times, it'll still stop at the ` accent, i.e. it'll die at the grave, with the error "E492: Not an editor command: the end" - this is the expected method of termination, and not a bug! You could also pepper these characters throughout your program as breakpoints.

Note on efficiency: Because the interpreter uses search quite a lot to move the "program pointer" around, search highlighting ends up slowing it down a lot, by one or two orders of magnitude. This means that running :set nohlsearch before a long run of steps will greatly speed up playback, while :set hlsearch to turn on search highlighting will slow it down a lot, so you can watch it operate a bit better (but epileptics beware: hlsearch being on causes a lot of flashing, including of the entire program text at the top!).

Note 1: There are special characters in this Gist (all the ^M characters), so copy/pasting the text may not work. You'll have to download it, either through "Download ZIP," or by clicking Raw and saving the raw version directly.

Note 2: Though this has a .vim extension, it is not a valid VimL script. Don't try to source/run it as one!

Tested and working in Vim 8.0, both in a fully defaulted vim ($ vim -u NONE), and in my heavily modified Vim with custom vimrc, hundreds of custom mappings, and 76 plugins. I attempted to use only Vim defaults in the interpreter, and I strive not to replace many of those in my own setup. YMMV.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment