From 706650f6f6a7a68cb64c269821d8a61edb26a9d0 Mon Sep 17 00:00:00 2001 From: Yong He Date: Wed, 14 Aug 2024 22:05:03 -0700 Subject: Design proposal for Tuple types. (#4848) * Design proposal for Tuple types. * formatting. --- docs/proposals/008-tuples.md | 137 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 docs/proposals/008-tuples.md (limited to 'docs') diff --git a/docs/proposals/008-tuples.md b/docs/proposals/008-tuples.md new file mode 100644 index 000000000..b1e62596f --- /dev/null +++ b/docs/proposals/008-tuples.md @@ -0,0 +1,137 @@ +SP #008 - Tuples +============== + +Now that we have variadic generics in the language following [SP #007], we should now be able to support `Tuple` type as a core language feature. +`Tuple` types are useful in many places to reduce boilerplate in user code, such as in function return types to eliminate the need of defining +`struct`s that are used only for invoking the function. Adding `Tuple` types to Slang will also simplify interop with other languages such as Python +and C++ that have tuple types. + +Status +------ + +Author: Yong He + +Implementation: In-progress. + +Reviewed by: N/A + +Background +---------- + +Tuple type is widely supported in almost all of the modern programming languages including C++, C#, Swift, Rust, Python. Supporting tuple types +in Slang will bring the language to parity with other languages and allow users to practice the same coding idioms in Slang, and allow Slang code +to interop more directly with other parts of the user application written in other languages. + + +Proposed Approach +----------------- + +With variadic generics support, we can now easily define a Tuple type in stdlib as: +``` +__generic +__magic_type(TupleType) +struct Tuple +{ + __intrinsic_op($(0)) + __init(expand each T); +} +``` + +This will allow users to instantiate tuple types from their code with `Tuple(v0, v1, v2)`. + +### Constructing Tuple Values + +To make it easy to construct tuples, we will define a `makeTuple` function in stdlib as: +``` +__intrinsic_op($(kIROp_MakeTuple)) +Tuple makeTuple(expand each T values); +``` + +With generic argument inferencing, this will enable user to write: +``` +makeTuple(1, 2.0f) // returns Tuple(1, 2.0f) +``` + +### Accessing Tuple Elements + +We can extend the logic of vector element accessing to access tuple elements. Given `t` as a tuple, these expressions are valid: +``` +t._0 // Access the first element +t._1 // Access the second element +``` + +### Swizzling + +We can easily support tuple swizzles: +``` +let t = Tuple(1, 2.0f); +let v = t._1_0; +// v == Tuple(2.0f, 1) +``` + +### Concatenation + +We can define tuple concatenation operation in stdlib as: +``` +Tuple concat(Tuple first, Tuple second) +{ + return makeTuple(expand each first, expand each second); +} +Tuple concat(Tuple first, expand each U second) +{ + return makeTuple(expand each first, expand each second); +} +``` + +Note that we can't have an overload that takes a type pack and append it to the beginning of a tuple yet, because we +currently don't support having type pack arguments that aren't at the end of an argument list. + + +### Counting + +The `countof` expression can be used on type packs or tuple values to obtain the number of elements in a type pack or tuple. +And this result should be usable as a compile-time constant such as in a generic argument. + +``` +int bar() +{ +} +int foo() +{ + bar(); // OK, countof T is a compile time constant. + + Tuple t; + let c = countof t; // OK, countof can be used on tuple values. +} +``` + +### Operator Overloads + +We should have builtin operator overloads for all comparison operators if every element type of a tuple conforms to `IComparable`. +This can be supported by defining an overload for these operators in stdlib in the form of: +``` +bool assign(inout bool r, bool v) { r = v; return v; } + +__generic +bool operator < (Tuple t0, Tuple t1) +{ + bool greater = false; + bool equals = true; + expand greater || assign(equals, equals && (each t0) == (each t1)) && assign(greater, (each t0) > (each t1)); + return !greater && !equals; +} +``` + + +Alternatives Considered +---------------- + +Should we allow other operator overloads for tuples? This seems useful to have, but right now this is a bit tricky +because we haven't really settled on builtin interfaces. We need to finalize things like `IFloat`, `IInteger`, +`IArithmetic`, `ILogic` etc. first. + +Should we automatically treat `Tuple` type to conform to any interface `IFoo` if every element in the tuple conforms to +`IFoo`? We can't because this is not well-defined. For example, if `IFoo` has a method that returns `int`, +should the tuple type's equivalent method return `Tuple` or just `int`? In some cases you want one but +other times you want the other. And if the method returns a tuple, it is no longer consistent with the base interface +definition so this is all ill-formed. \ No newline at end of file -- cgit v1.2.3