rune icon indicating copy to clipboard operation
rune copied to clipboard

Add support for matching over external enums and unit structs

Open udoprog opened this issue 2 years ago • 0 comments

We currently only support matching over external structs, such as:

#[derive(Any)]
struct External {
    #[rune(get)]
    field: u32,
}

Which would allow for the following in Rune:

pub fn main(external) {
    match external {
        External { field } => field,
    }
}

These are currently not supported, but both could and should be:

Tuple structs

#[derive(Any)]
struct External(#[rune(get)] u32);

In Rune:

pub fn main(external) {
    match external {
        External(field) => field,
    }
}

Enum variants:

#[derive(Any)]
enum External {
    First,
    Second(#[rune(get)] u32),
    Third {
        #[rune(get)]
        field: u32,
    }
}

In Rune:

pub fn main(external) {
    match external {
        External::First => {},
        External::Second(field) => field,
        External::Third { field } => field,
    }
}

Implementation details

It is necessary to add getters for accessing fields of external types, because Rune has no other way of doing so. It's also a natural extension of how #[rune(get)] currently works. I.e. it permits external.field to work as intended.

This requires that field functions are extended to be capable of addressing the "numeric indexes" of tuples. Which is perfectly doable but would require additional APIs to Module. Similar to how we have Module::field_fn it might be appropriate to add Module::tuple_fn.

In order to support enums we also need additional ways to register enum metadata. in #384 we introduced Module::struct_meta which is used for registering the limited amount of metadata necessary to compile matches over structs. For enums this would have to be much more exhaustive. What we need it to register is:

  • A collection of all the variant names.
  • For each variant, if they are struct, tuple, or empty.
  • For struct variants, the names of its fields.
  • For tuple variants, how many items it has. E.g. Foo(a, b) has 2 items.

udoprog avatar Jan 09 '22 19:01 udoprog