# meow5 **Source:** https://ratfactor.com/meow5/ Meow5: An Extremely Concatenative Programming Language - ratfactor [![vector ratfactor rat logo](/images/rat-logo.svg)](/) [Home](/) | [About](/about/) | [Now](/now) | [Repos](/repos/) | [Cards](/cards/) | [Contact](/contact-me/) | [RSS![rss feed icon](/images/rss.svg)](/atom.xml) # Meow5: An Extremely Concatenative Programming Language Created: 2022-11-10 Updated: 2023-11-21 ![meow5 kitty logo is black with two bright teal eyes and a pink nose](meow5.png) **Update 2023-11-21:** Meow5 is done! [Read my conclusion here!](done) Meow5 is a ["concatenative"](https://en.wikipedia.org/wiki/Concatenative_programming_language) (wikipedia.org) programming language. I also consider it to be a "Forth-like" language since it follows the same stack-based value passing method and borrows some of Forth’s syntax and nomenclature. Hello world (in cat): ``` "Meow!" print Meow! ``` * **The Repo:** [Meow5 Repo](/repos/meow5/) * **Read more:** [Assembly Nights "Season 2"](../assembly-nights2) might explain why I would do something like this **Update 2023-11-01:** Well, would you look at that? It’s just shy of a year after I started this and I think I’m actually going to be able to finish [it](done) quite soon. (To see where I’m currently at, scroll down to **Current progress** below.) It’s unique feature is its "inline all the things!" compiling method. A Meow5 function is the recursively concatenated machine code of every function it calls. At the bottom are "primitive" functions written in assembly language, which is where the machine code comes from. Wait, you mean every time I call a function in another function, I’m making a complete copy of that function, which is a complete copy of every function *that* function calls, all the way down? Yup! Pretty nuts, right? Feel free to run away from this page screaming now. But when a primitive is just a dozen bytes long, you can make quite a few copies of it before it’s a problem. I’m very curious to see how it benchmarks against other languages in various ways: size, speed, cuteness. ## Syntax Meow5 borrows heavily from the ur-language **Forth**, which was delivered to our dimension by the prophet Charles H. Moore in the late 1960s. Creating a new function, `meow`, that prints the string "Meow" looks like this: ``` : meow "Meow." print ; ``` Creating a another function, `meow5`, which executes `meow` five times: ``` : meow5 meow meow meow meow meow ; ``` Invoke their names to call these functions: ``` meow Meow. meow5 Meow.Meow.Meow.Meow.Meow. ``` That’s a lot of meows! Who’s a hungry kitty? To drive home an earlier point: the above `meow5` function doesn’t just *call* `meow` five times, it actually *contains* five consecutive copies of `meow`! ## Current Progress Here’s a list of milestones reached. The log text file references are from my devlog files which I write as I’m creating Meow5. You can find them in the repo! (Note to self, when I put the logs up here like I did for [nasmjf](../nasmjf/), link these!) * (log01.txt) Executing a *copy* of the machine code to print "Meow" at runtime * (log01.txt) Programatically inlining multiple copies of the "Meow" printer * (log02.txt) Added function "tail" metadata for linked list dictionary, to use Forth terminology * (log02.txt) Added `find` function to lookup functions by name for inlining * (log03.txt) Figured out how to call these machine code chunks so they can return to the call site * (log03.txt) Have interpreter parsing tokens from a hard-coded input string and executing them * (log04.txt) Have COMPILE vs IMMEDIATE modes and functions may opt-in for either * (log05.txt) Using NASM macros to inline functions at the assembly level to build interpreter * (log05.txt) **Major:** Finished `:` ("colon") and `;` ("semicolon") for function definitions! * (log06.txt) Added string literals to the language can do this: `"Meow!" print` * (log06.txt) Have string literals working in *compiled* functions! * (log06.txt) DEBUG printing (can be inserted anywhere in the assembly) * (log06.txt) **Major:** The canonical `meow5` function works as shown on this page! * (log07.txt) Added `str2num` and `num2str` for numeric input/output * (log07.txt) Have numeric interpolation in strings with `$` placeholders * (log07.txt) Have string escape sequences (e.g. `\n`) * (log07.txt) Functions 'inspect' and 'inspect\_all' print all functions with size in bytes * (log08.txt) **Major:** Reading interpreter input from STDIN! **TODO:** The above are badly in need of updating and links. **Update 2023-11-01:** I’ve finished the [mez](/repos/mez/) tools in Zig to help me understand, create, and debug ELF executables and feel fully capable of finishing the ELF output of Meow5. Let’s do this! Also: "failed art project" below was waaay too harsh. It’s going to be a successful art project! **Update 2023-10-17:** Five months later, I’m back. I essentially consider this to be a failed art project, but I am not willing to let it rest until it compiles an ELF executable that prints "Meow" five times! ``` >o.o< --"Why yes, I do speak ASCII!" ``` ## Technical Details **32-bit x86 Linux:** Meow5 is written with the NASM assembler () and targets the 32-bit i386 (x86) architecture. It makes direct Linux syscalls and uses no external libraries. Portability is not a goal. **Stack-oriented:** Meow5 uses the i386 `PUSH` and `POP` instructions in the normal fashion to set/get items from the stack (a region of memory to which items are added or removed sequentially in a "first in, last out" fashion). One thing that’s neat about this is that alleviates the difficult task of putting names to data. It also generally produces compact and uncluttered syntax. **Just in Time Compiled:** The moment you start compiling a new function `foo`, it’s machine code is being inlined into memory. When you execute `foo`, a `JMP` instruction is issued to its machine code, which then runs until it hits a chunk of "return code" inlined at the end of the definition, which jumps back to the call site. It does not use `CALL` and `RET` and there can be only *one* level of direct function call in this fashion, which, it turns out, is all you need for an interactive Meow5 interpreter. **Inline All the Things!:** If you use function `foo` in the definition of a new function `bar`, the machine code of `foo` (not including the "return code" mentioned above or the "tail" with function metadata) is inlined into `bar`. The logical conclusion is that a Meow5 **program** is a top-level function containing a continuous stream of concatenated machine code. What I would like to do at some point is write out such a program with an ELF header and see if I can make stand-alone Linux executables! ## OpenBSD I was really curious what OpenBSD would think of this since my understanding is that it has [W^X (wrote xor execute)](https://en.wikipedia.org/wiki/W%5EX) by default. Sure enough, even the linker catches this: ``` ld: error: can't create dynamic relocation R_386_32 against local symbol in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output >>> defined in meow5.o >>> referenced by meow5.asm:167 >>> meow5.o:(tail_strlen) ``` which is in reference to: ``` %macro ENDWORD 3 ... tail_%1: dd LAST_WORD_TAIL ; <---- this line ``` Where I’m putting the address of the previous function in the tail of the current one to make a linked list. I’m not sure what those two suggested options are. I might try them to see how far I get. --- I made the SVG Meow5 logo in Inkscape 0.92. It uses the **Sazanami Mincho** font by Yasuyuki Furukawa. *Mincho* evidently means something very similar to what 'serif' means in Latin typefaces. See [Ming typefaces](https://en.wikipedia.org/wiki/Ming_(typefaces)) (wikipedia.org). This page was last generated 2023-11-21 15:13:54 -0500 All content © Copyright Dave Gauer