hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.23k stars 224 forks source link

[SUGGESTION] Let us write std::array as if it were a built in array for cppfront #1132

Open 12345swordy opened 1 week ago

12345swordy commented 1 week ago

I.E.

numbers: int[]= ( 1, 2 );

which corresponds to

numbers: std::array<int,2> = ( 1, 2 );

It eliminates guidance literature of having to tell them to use std::array instead of c++ built in array, by having the std::array be the default building block, when using the built in array for cppfront.

hsutter commented 1 week ago

Thanks! A number of folks have requested this (I can't quickly find a link to prior discussion, sorry), and I've been resisting it.

First, a question: Should each of the following be legal, and should they mean the same thing?

numbers: int[2] = ( 1, 2 );
numbers: int[ ] = ( 1, 2 );
numbers:    [ ] = ( 1, 2 );

Should int[] be an array with deduced length, or a span which is a more commonly used type and so probably should get language support first? If we say int[] is span and int[N] is an array like some languages do, so that it depends on whether there's an integer length value, then we lose a syntax that deduces the length because we made int[] mean something else. Also, my understanding that in languages that do that there's sometimes confusion when int[] is a non-owning view (slice) and int[10] is an owning container (array) because the syntactic difference is subtle.

My view is that if we did add language support for std::array using any of those syntaxes, then all three of those should mean the same thing, namely a std::array. But that would mean we give arrays (fixed-size containers by value) preference over spans (which are more common).

In the above example:

I.E.

numbers: int[]= ( 1, 2 );

OK, so the suggestion is that this declare a std::array with deduced length 2.

which corresponds to

numbers: std::array<int,2> = ( 1, 2 );

Interestingly, a 2 crept in there... I think what you're suggesting is that it should actually correspond to B below (not C), because the original code above deduces the length:

std::array        numbers = ( 1, 2 );  // A - ok
std::array<int  > numbers = ( 1, 2 );  // B - except this is an error
std::array<int,2> numbers = ( 1, 2 );  // C - ok

but C++ CTAD doesn't allow B, it only allows A and C. And because Cpp2 is lowered to the above from:

numbers: std::array        = ( 1, 2 );  // A2 - ok
numbers: std::array<int  > = ( 1, 2 );  // B2 - error
numbers: std::array<int,2> = ( 1, 2 );  // C2 - ok

so today A2 and C2 work in Cpp2 but not B2 (though we could make it work by special-casing std::array).

Those are some thoughts.

12345swordy commented 1 week ago

Here is the prior discussion for reference: https://github.com/hsutter/cppfront/discussions/637

AbhinavK00 commented 1 week ago

Let's assume that int[] is an array of deduced length for now. That means the following will give us std::array<int, 3>.

numbers : int[] = (1, 2, 3);

All good for now. But for functions declaring parameters of array type,

func : (arr1 : i32[], arr2 : i64[]) = {
}

This won't work because a parameter of std::array<int> is invalid, (cppfront could generate a templated function but that would probably be the worst way to go about this IMHO). That's why I think that T[] should spell a span of Ts, instead of an array. Arrays with deduced size can be spelled using T[_] if they're allowed. Also, maybe the syntax []T can be considered to be consistent with pointers.

12345swordy commented 1 week ago

The issue that I see right now is the much needed distinction between static array and dynamic array. As noticed in the discussion that I linked, vector have bad abi design The example that I initially give is what I considered to be a static array with deduced length.