diff options
| author | Yong He <yonghe@outlook.com> | 2024-08-14 22:05:03 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-14 22:05:03 -0700 |
| commit | 706650f6f6a7a68cb64c269821d8a61edb26a9d0 (patch) | |
| tree | 3f4b7a353ec282f9791064159272417431168016 /docs | |
| parent | 071f1b6062b459928ebfd6f2f60a8d6ad021112b (diff) | |
Design proposal for Tuple types. (#4848)
* Design proposal for Tuple types.
* formatting.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/proposals/008-tuples.md | 137 |
1 files changed, 137 insertions, 0 deletions
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<each T> +__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<T0, T1, T2>(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<expand each T> makeTuple(expand each T values); +``` + +With generic argument inferencing, this will enable user to write: +``` +makeTuple(1, 2.0f) // returns Tuple<int, float>(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<int, float>(1, 2.0f); +let v = t._1_0; +// v == Tuple<float, int>(2.0f, 1) +``` + +### Concatenation + +We can define tuple concatenation operation in stdlib as: +``` +Tuple<expand each T, expand each U> concat<each T, each U>(Tuple<expand each T> first, Tuple<expand each U> second) +{ + return makeTuple<expand each T, expand each U>(expand each first, expand each second); +} +Tuple<expand each T, expand each U> concat<each T, each U>(Tuple<expand each T> first, expand each U second) +{ + return makeTuple<expand each T, expand each U>(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<let n : int>() +{ +} +int foo<each T>() +{ + bar<countof T>(); // OK, countof T is a compile time constant. + + Tuple<expand each T> 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<each T : IComparable> +bool operator < (Tuple<T> t0, Tuple<T> 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<expand(int, T)>` 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 |
