Proc Macro Workshop: derive(Builder) [Part 1]

While continuing to learn a bit more about macros in Rust (previous post), I really want to move beyond the simple declarative macros and get into something a bit more interesting. Enter procedural macros. In a nutshell, procedural macros in Rust, rather than relying entirely on pattern matching and expansion are fully Rust functions.

They take a specific input (a stream of tokens) and output a specific output (a new stream of tokens), but in between they can do just about anything a full Rust function can do. And what’s better yet… they operate at compile time. And because they operate on tokens (rather than a full AST), you can do things that just aren’t syntactically valid in normal Rust. Things like… variadic functions (a la print! or var!) or even crazier things like embedding Python in Rust for … reasons.

Today specifically, I’ve started working through the prod-macro-workshop repo. It’s a series of five examples macros with test cases and some guidance set up to help you get up to speed. I’m going to be working through the first of these: derive(Builder). Now don’t get me wrong. I really have no idea what I’m doing, so don’t take this as an example of how to write a macro. But perhaps by writing this out, it will help me learn it better… and if you happen to learn something as well, all the better!


Writing a curry! macro for MacroKata

Recently I’ve been wanting to learn more about macros in Rust. It was always one of my favorite parts of Racket, so let’s see what we can do.

In order to do that, I’ve been following the excellent MacroKata series. It goes all the way through, starting with the very basics, adding in literals and expressions, handling repetition, nesting, and finally recursion.

What I really want to talk about those is the one that I found most interesting: curry!.


AoC 2017 Day 23: Duetvmc

Source: Coprocessor Conflagration

Part 1: Create a variation of the previous DuetVM with only the following four instructions:

  • set X Y sets register X to Y
  • sub X Y set register X to X - Y
  • mul X Y sets register X to X * Y
  • jnz X Y jumps with an offset of the value of Y, iff X is not equal to zero

If you run the given program, how many times is mul invoked?


'Tiny' Turing completeness without MMOV

Something was bugging me about my proof from yesterday. If we take another tack on proving Turing completeness, all we would have to prove is that we can simulate `SUBLEQ`. Since SUBLEQ is Turing complete, that’s all we need–just convert each SUBLEQ into a SUB, JZ, and a JLS. So that means that Tiny as written should be Turing complete.

So how does that work?


A 'Tiny' virtual machine in Racket

Today’s challenge at /r/dailyprogrammer asks to implement an assembler for a small virtual machine. It has only 16 mnemonics which in unique opcodes (each instruction can have multiple forms for if they’re accessing memory or literals), so it’s a simple virtual machine indeed. As a challenge, you’re supposed to write an interesting program (I actually wrote a virtual machine as well to test them). As an even better challenge, we’re supposed to prove that Tiny is Turing complete. Well, let’s get to it!