jakt icon indicating copy to clipboard operation
jakt copied to clipboard

Static Reflection

Open alimpfard opened this issue 2 years ago • 3 comments

It would be super nice to support this as it remains a major pain point of C++ (at least for myself); introspection of types being the main desired feature

  • the keyword reflect
  • an expression of the form reflect type-name
  • Implementation requirements:
    • Should present a meaningful interface to the user, perhaps through predeclared types
    • Should work with generic types
    • Should have all the information to reconstruct the reflected type (though not required for basic functionality)

small example (syntax is made-up and not decided)

enum Foo<T> {
    Var0: T
    Var1: i32
}

function foo() -> String {
	return match reflect Foo {
        Enum(variants: vs) {
            vs.first().name
        }
        _ => verify_not_reached()
    }
}

alimpfard avatar May 20 '22 18:05 alimpfard

Instead of introducing a new keyword, why not do what Zig does and treat types like objects of type Type? Type would act like a compile time struct with some fields like name and an enum of enum, class, struct, function, etc. And each of those would have fields that describe them. So, for function the API would look like:

struct Function {
    name: String,
    arguments: Array<Variable>,
    return_type: Type,
    block: Array<Statement> // Maybe.
}

And it would be used like:

function foo() {
    return match foo.type {
        Function(function: f) => f.name + " returns " + f.return_type.name
        // ...
    }
}

And for enum:

enum BetterOptional<T> {
    Some(T)
    None
}

function bar() {
    return match BetterOptional.type {
        Enum(variants: vs) => vs[0].name // If indexing past Array, throw error at compile time.
        // ...
    }
}

Not exactly sure what the expected behavior would be when taking the name of a templated type, so maybe it would only be valid if either the type has its templates filled out or you don't touch T.

juniorrantila avatar May 26 '22 07:05 juniorrantila

I'm fairly against pretending that typenames are values, we don't have type-level computations, and we don't have kinds, so T wouldn't actually be a "type", it'd have to be magically reflected if you name it as an expression instead of implicitly doing so, we can keep the parser simpler with a keyword and call it good.

note that my suggestion doesn't place compile-time execution restrictions, reflect(T) is a runtime value.

alimpfard avatar May 26 '22 13:05 alimpfard

Slowly moving, but I've got a partial implementation working in https://github.com/alimpfard/jakt/tree/sr. With the CTFE support present, it's relatively simple to do - just need some time to support enough to be useful.

alimpfard avatar Aug 16 '22 20:08 alimpfard