Question

I'm writing a compiler that compiles to C, one thing I'm attempting to do is implement a construct like Rust's match:

// { some function
    let mut foo = 32;
    match foo {
        3 => return "hey",
        4 | 5 | 6 => return "foo",
        9 ... 12 => return "blah",
        _ => return "bar",
    }
// }

How would a construct like this look in C code? I was thinking something simple like this could be a switch construct like so:

switch (foo) {
    case 3: return "hey";
    case 4: case 5: case 6: return "foo";
    case 9: case 10: case 11: case 12: return "blah";
    default: return "bar";
}

And most importantly, how would it look for more complicated examples like this:

let pair = (0, -2);

match pair {
    (0, y) => println!("First is `0` and `y` is `{:?}`", y),
    (x, 0) => println!("`x` is `{:?}` and last is `0`", x),
    _      => println!("It doesn't matter what they are"),
}

Where the tuple is destructured and can handle values too?

Was it helpful?

Solution

Let's consider a super basic example. Your language only has two types, int and pair. Pairs can hold other pairs. For your "cases", you also have unbound variables.

So when you pass in the value to match, you can have an int or a pair. The pattern to match can be an int, a pair, or an unbound-variable. The pattern matching algorithm then goes:

if my pattern is an int, and the input is an int, if they're equal, do this.
if my pattern is a var, assign the value to the var, and do this.
if my pattern is a pair, and the input is a pair, then if 
    pattern-match(pattern.first, value.first) && 
    pattern-match(pattern.second, value.second), do this.
otherwise, try the next pattern.

For basic Lisps, which only have symbols and pairs - that's all they need. For other languages, you may need to extend the basics to handle other types, and maybe other structures.

And hopefully you can see how this becomes dicey once you have mutable state.

Licensed under: CC-BY-SA with attribution
scroll top