From 69e0f878e02d61280110b379f9d346acde7575a8 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 28 Aug 2024 22:26:50 -0700 Subject: Update `IFunc` proposal to reflect its implementation. (#4950) --- docs/proposals/009-ifunc.md | 67 +++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 29 deletions(-) (limited to 'docs') diff --git a/docs/proposals/009-ifunc.md b/docs/proposals/009-ifunc.md index 646f5f55b..373e2dedc 100644 --- a/docs/proposals/009-ifunc.md +++ b/docs/proposals/009-ifunc.md @@ -10,9 +10,11 @@ Status Author: Yong He -Implementation: Planned. +Status: Implemented. -Reviewed by: N/A +Implementation: [PR 4905](https://github.com/shader-slang/slang/pull/4905) [PR 4926](https://github.com/shader-slang/slang/pull/4926) + +Reviewed by: Kai Zhang, Jay Kwak Background ---------- @@ -57,49 +59,50 @@ eliminating the need for defining interfaces and wrapper types. Proposed Approach ----------------- -We propose `IFunc` and `IMutatingFunc` that is defined as follows: - +We should support overloading of `operator()`, and use the function call syntax to call the `operator()` member, similar to C++: ``` -// Function objects that does not have a mutating state. -interface IFunc +struct Functor { - TResult __call(expand each TParams params); + int operator()(float p) {} } -// Function objects with a mutating state. -interface IMutatingFunc +void test() { - [mutating] - TResult __call(expand each TParams params); + Functor f; + f(1.0f); } ``` -Ordinary functions are treated as conforming to `IFunc` and `IMutatingFunc` automatically, -so the following code is valid: +We propose `IFunc`, `IMutatingFunc`, `IDifferentiableFunc` and `IDiffernetiableMutatingFunc` that is defined as follows: ``` -int countElement(int data[100], IFunc condition) +// Function objects that does not have a mutating state. +interface IMutatingFunc { - int count = 0; - for (int i = 0; i < data.getCount(); i++) - if (condition(data[i])) - count++; - return count; + [mutating] + TR operator()(expand each TP p); } -int myCondition(int x) { return x%2 == 0; } // select all even numbers. +// Function objects with a mutating state. +interface IFunc : IMutatingFunc +{ + TR operator()(expand each TP p); +} -void test() +// Differentiable functions +interface IDifferentiableMutatingFunc : IMutatingFunc { - int data[100] = ...; - int count = countElement(data, myCondition); + [Differentiable] + [mutating] + TR operator()(expand each TP p); } -``` -An ordinary function or static function with type `(T0, T1, ... Tn)->TR` is coerceable to `IFunc` if -`TI0, TI1, ... TIn` are coerceable to `T0, T1, ... Tn` and `TR` is coerceable to `TIR`. -To achieve this, the compiler will synthesize a wrapper struct type conforms to the `IFunc` interface, and calls the original function -in its `__call` method. +interface IDifferentiableFunc : IFunc, IDifferentiableMutatingFunc +{ + [Differentiable] + TR operator()(expand each TP p); +} +``` The `IMutatingFunc` interface is for defining functors that has a mutable state. The following example demonstrates its use: @@ -115,7 +118,7 @@ struct CounterFunc : IMutatingFunc int count; [mutating] - void __call(int data) + void operator()(int data) { if (data % 2 == 0) count++; @@ -131,3 +134,9 @@ void test() printf("%d", f.count); } ``` + +# Coercion of ordinary functions + +Eventually, we should allow ordinary functions to be automatically coerceable to `IFunc` interfaces. But this is scoped out +for the initial `IFunc` work, because we believe the implementation can be simpler if we support lambda function first, then +implement ordinary function coercion as a special case of lambda expressions. \ No newline at end of file -- cgit v1.2.3