- Like many Lisps, Fennel is extremely permissive about what it considers to be valid identifiers in code so long as delimiters like
()[]{}
are properly respected and known identifiers/symbols (builtin macros/special forms, known functions, etc) are left alone. - And by anything, I do mean anything.
- Zalgo-text generators have been pretty popular lately; they more or less just dump patterns of garbage unicode codepoints between the actual characters in strings until computers can no longer properly render it. It's pretty funny; sometimes it will look different in different contexts even in the same application on the same machine.
- So why the hell not, let's have Fennel compile itself to zalgo.
In the first 80 or so lines of zalgo.fnl, you'll see a quick and dirty implementation of one of these cursed text generators. Then, starting on line 82, we wrap the whole thing in a Fennel macro. All it's really doing is walking the syntax tree so that every symbol that doesn't already exist in the compiler's scope (because we want to be able to invoke pre-existing functions and macros), accessing the symbol's underlying string, and promptly injecting it with trash unicode beffore letting the compiler take it from there.
That's more or less it! You can see what the processed Fennel looks like from the macrodebug
call in teste-zalgo.fnl
below. That's the code it will ultimately turn into lua and evaluate to get the printed output in the screenshot above.
That would be this horrible mess:
The test-zalgo.fnl
file below totals somewhere around 800 bytes; the actual code we're corrupting weighs in at less than half of that, while the lua generated by (curse ...)
on just those 400-or-so bytes brings it to about 65kb of mostly escaped unicode bytes like you see above. Yes, this is absolutely pointless, but if you're still reading this it means that, like me, you also enjoy shitposting-as-code. Welcome!