You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Initial support for user-defined initializer/constructor declarations (shader-slang#1233)
The basic idea is that the user can write:
```hlsl
struct MyThing
{
int a;
float b;
__init(int x, float y)
{
a = x;
b = y;
}
}
```
and after that point, they can create an intstance of their `MyThing` type as simply as `MyThing(123, 4.56f)`.
There was already a large amount of infrastructure laying around that is shared between ininitializers and ordinary functions, so enabling this feature mostly amounted to tying up some loose ends:
* In the parser, make sure to properly push/pop the scope for an `__init` (or `__subscript`) declaration, so parameters would be visible to the body
* In semantic checking, make sure that declaration "header" checking properly bottlenecks all the function-like cases into a base routine
* In semantic checking, make sure that the logic for checking function bodies applies to every `FunctionDeclBase` with a body, and not just `FuncDecl`s
* Update semeantic checking for statements to allow for any `FunctionDeclBase` as the parent declaration, not just a `FuncDecl`
* In lookup, treat the `this` parameter of an `__init` (well, not actually a *parameter* in this case) as being mutable, just like for a `[mutating]` method
* In IR codegen, don't just assume that all `__init`s are intrinsics, and narrow the scope of that hack to just `__init`s without bodies
* In IR codegen, detect when we are emitting an IR function for an `__init`, and in that case create a local variable to represent the `this` value, and implicitly return that value at the end of the body.
From that point on the rest of the compiler Just Works and IR codegen doesn't have to think of an `__init` as being any different than if the user had declared a `static MyThing make(...)` function.
Caveats:
* C++ users might like to use that naming convention (so `MyThing` as the name instead of `__init`). We can consider that later.
* Everybody else might prefer a keyword other than `__init` (e.g., just `init` as in Swift), but I'm keeping this as a "preview" feature for now, rather than something officially supported
* Early `return`s from the body of an `__init` aren't going to work right now.
* There is currently no provision for automatically synthesizing initializers for `struct` types based on their fields. This seems like a reasonable direction to take in the future.
* There is no provision for routing `{}`-based initializer lists over to initializer calls. The two syntaxes probably need to be unified at some point so that doing `MyType x = { a, b, c }` and `let x = MyType(a, b, c)` are semantically equivalent.
It is possible that as a byproduct of this change user-defined `__subscript`s might Just Work, but I am guessing there will still be loose ends on that front as well, so I will refrain from looking into that feature until we have a use case that calls for it.
0 commit comments