Index: doc/proposals/tuples.md
===================================================================
--- doc/proposals/tuples.md	(revision 1b770e40a9aa780c070c74b549d1a0de6566d6b8)
+++ doc/proposals/tuples.md	(revision 63cf80ece801d108fffabf9a0780fd39c591a632)
@@ -2,9 +2,10 @@
 ======
 
-Tuples were introduced by Dave Till in K-W C, added to CFA by Rodolfo Esteves,
-and extended by Robert Schluntz. This proposal discusses updates for CFA tuples
-to address problems that have appeared in their usage over the past 6 years.
-The proposal attempts to address problems by adding new functionality, updating
-existing features, and removing some problematic ones.
+This is a proposal discusses update to Cforall tuples as they exist after
+the work done by Robert Schluntz (after they were added to Cforall by
+Rodolfo Esteves and to K-W C by Dave Till). The new features and ideas
+discussed here are designed to address problems that have appeared as tuples
+have been used in the past 6 years. Some or all of the changes discussed may
+already be implemented.
 
 The core change is breaking the current restructurable tuples into unstructured
@@ -14,5 +15,5 @@
 Current State of Tuples
 -----------------------
-An overview of the current tuples design is the starting place for the proposal.
+An overview of the current tuple design is the starting place for the proposal.
 
 ### Tuple Syntax
@@ -22,23 +23,25 @@
 (deconstructing tuples).
 
-Current syntax for tuple types.
+Current syntax for tuple types:
 
 -   Nullary: [void] or []
+
+	[void] f();
+	[] f();
+
 -   Unary: [TYPE]
--   Nary: [TYPE, TYPE, ...]
-
-Tuple types can appear in a function return and parameter declaration, or a
-tuple variable declaration. Note, the Nullary tuple is only meaningful in the
-return context,
-
-	void f(...);   // equivalent
-	[void] f(...);
-	[] f(...);
-
-as C does not support a void declaration.
-
-	int f( void x );    // disallowed
-	int f( [void] x );
-	int f( [] x );
+
+	[int] f();
+	[double] x = 1.5;
+
+-   Multiary: [TYPE, TYPE, ...]
+
+	[bool, char] f();
+	[short, int, long] x;
+
+Tuple types can appear anywhere regular types may be used, except for the
+nullary tuple which can only appear where void can be used (usually return
+types), with the exception of special case when void is used to make an empty
+parameter list.
 
 Current syntax for tuple expressions:
@@ -46,29 +49,25 @@
 -   Nullary: (Same as `void`, use return without an expression.)
 
-	[] f( ) { return; }
-	[] f( ) { return [] ; }
-
--   Unary:
-
-	[int] f( ) { return 3; }
-	[int] f( ) { return [3]; }
-
--   Nary: [EXPR, EXPR]
-
-	[int,int] f( ) { return [3,4]; }
-
-Currently, there is a parsing problem for nullary and unary tuple expression,
-which is being looked at. Hence, only these two forms work.
-
-	[] f( ) { return; } // nullary
-	[int] f( ) { return 3; } // unary
-   
+	[] f() { return; }
+
+-   Unary: EXPR (in return only) or {EXPR}
+
+	[int] f() { return 3; }
+	[int] x = {3};
+
+-   Multiary: [EXPR, EXPR, ...]
+
+	[int, int] f() { return [3, 4]; }
+	[bool, char, int] x = [true, 'a', 3];
+
+Tuple expressions should be useable whenever an expression of that type is
+expected. Issues with the current state will be discussed later.
+
 Current syntax for tuple indexing is an integer constant, where its value
 selects a tuple member, e.g.:
 
-	[char, int] tup;
-	tup = ['a', 0];
-	char ch = t.0; // select first tuple member
-	int value = t.1; // select second tuple member
+	[char, int] tup = ['a', 0];
+	char ch = tup.0;
+	int value = tup.1;
 
 ### Mass and Multi-Assignment
@@ -79,14 +78,16 @@
 
 	[int, long, float] dst;
-	int src = 4
-	dst = src;  // => dst.0 = src; dst.1 = src; dst.2 = src
+	int src = 4;
+	dst = src;
+	// Becomes: dst.0 = src; dst.1 = src; dst.2 = src;
 
 Multi-assignment assigns every element in the destination tuple to the
 corresponding element in the source tuple. Both tuples must be the same size
-and the elements assignment compatible => conversions.
+and the elements pairs must be assignment compatible conversions.
 
 	[long, int, float] dst;
 	[int, char, double] src = [1, 'a', 300.0];
-	dst = src;   // => dst.0 = src.0; dst.1 = src.1; dst.2 = src.1
+	dst = src;
+	// Becomes: dst.0 = src.0; dst.1 = src.1; dst.2 = src.1;
 
 ### Tuple Restructuring
@@ -110,18 +111,4 @@
 	parmFunc(fst.0, fst.1, snd.0, snd.1);
 
-There are few languages supporting multiple return-values as a standalone
-feature (SETL). Go has multiple return-values but restricts their use in
-matching arguments to parameters.
-
-	func argFunc() (int, int) {
-	    return 3, 7
-	}
-	func parmFunc( a int, b int ) {
-	     fmt.Println(a, b )
-	}
-	func main() {
-	     parmFunc2( argFunc() ); // arguments must match exactly with parameters
-	}
-
 ### Tuple Casts
 
@@ -150,6 +137,7 @@
 	[int, [bool, char], int] w;
 	[i, b, c, i] = w;
-	[i, b, c, i] = ([int, bool, char, int])w; // fails
-	[i, b, c] = ([int, [bool, char]])w; // works
+	[i, b, c] = ([int, [bool, char]])w;
+	// But this does not work:
+	[i, b, c, i] = ([int, bool, char, int])w;
 
 ### Polymorphic Tuple Parameters
@@ -160,31 +148,43 @@
 sequence of types.
 
-	forall( T | { int ?>?( T, T ); } )
-	T max( T v1, T v2 ) { return v1 > v2 ? v1 : v2; }  // base case
-
-	forall(T, Ts... | { T max(T, T); T max(Ts); })  // recursive case
+	// Fixed Length Max - Base Case:
+	forall(T | { int ?>?( T, T ); })
+	T max(T v1, T v2) { return v1 > v2 ? v1 : v2; }
+
+	// Variable Length Max - Recursive:
+	forall(T, Ts... | { T max(T, T); T max(Ts); })
 	T max(T arg, Ts args) {
 		return max(arg, max(args));
 	}
 
-This feature introduces a type name into scope (Ts). It is used as a type but
-because the tuple is flattened, the second assertion "T max(Ts);" matches types
-with multiple parameters (the `...`), although it is used as a tuple function
-inside the function body (max(args)).
-
-The first non-recursive max function is the polymorphic base-case for the
-recursion, i.e., find the maximum of two identically typed values with a
-greater-than (>) operator.  The second recursive max function takes two
-parameters, a T and a Ts tuple, handling all argument lengths greater than two.
-The recursive function computes the maximum for the first argument and the
-maximum value of the rest of the tuple.  The call of max with one argument is
-the recursive call, where the tuple is converted into two arguments by taking
-the first value (lisp car) from the tuple pack as the first argument
-(flattening) and the remaining pack becomes the second argument (lisp cdr).
-The recursion stops when the tuple is empty.  For example, max( 2, 3, 4 )
-matches with the recursive function, which performs return max( 2, max( [3, 4]
-) ) and one more step yields return max( 2, max( 3, 4 ) ), so the tuple is
-empty.
-
+This feature introduces a type name into scope (Ts). It is used as a type and
+the value it declares (args) is a tuple value, and that the second assertion
+"T max(Ts);" matches takes a single tuple, but with restructuring it can also
+match functions that take a series of non-tuple arguments.
+
+A good way to explain this is to show a partial implementation the following
+call `max(int_a, int_b, int_c);` into actual code:
+
+	void _thunk0(int v1, int v2) {
+		return max{?>?}(v1, v2);
+	}
+	void _thunk1([int, int] tup) {
+		return max{?>?}(tup.0, tup.1);
+	}
+	max{_thunk0, _thunk1}(int_a, [int_b, int_c]);
+
+The part to highlight is that "_thunk1", one of the functions created to
+make an inexact match that can be used as a call site into an exact match
+so the function can be passed through function parameters.
+Although, the tuple type `[int, int]` matches a parameter list `int, int`,
+just with a bit of low lever restructuring.
+
+In larger cases (with four or more parameters in the first case), the
+recursive case will work similarly, creating an intermidate function to
+restructure the tuple into a new call such as:
+
+	void _thunk2([int, int, int] tup) {
+		return max{_thunk0, _thunk1}(tup.0, [tup.1, tup.2]);
+	}
 
 Issues with the Current State
@@ -199,15 +199,22 @@
 be.
 
-Because of the fluid nature of tuples (flattening/structuring), routines like
-constructions, destructor, or assignment do not make sense, e.g. this
-constructor matches multiple a tuple types:
-
-	void ?{} ( [int, int, int] ? this );
-	[int, [int, int]] x; // all match constructor type by flattening
-	[int,  int, int]  y;
-	[[int, int], int] z;
-
-as could a similarly typed destructor or assignment operator.  This prevents
-tuples from being interwoven with regular polymorphic code.
+Tuples do not have the lifetime operators (copy construction, copy assignment
+and destructor) that define an object type in Cforall. This means they are
+not polymorphic otypes, they are objects in C's usage of the word. This means
+that tuples cannot be used as a single object in
+
+There are several reasons for this. The fluid nature of tuples (flattening
+and restructuring) means that matching against a tuple type is fluid in some
+inconvent ways.
+
+	forall(T, U) void ?{}([T, U] & this;
+	void ?{}([int, int, int] & this);
+	// What constructor(s) should be used here?
+	[int, [int, int]] pair;
+
+Should the polymorpic constructor be applied twice or should the tuple be
+restructured and the three element constructor be used? This is not really
+something a user should be wondering about (especially since tuples should
+always be simple containers wrapping their elements).
 
 ### Providing TType Arguments is Inconsistent
@@ -217,35 +224,55 @@
 functions and there are very few existing use-cases for ttype structures.
 
-Passing arguments to a function inlines the arguments
-while passing them to a polymorphic type requires them to be
-enclosed in a tuple. Compare `function(x, y, z)` with `Type(A, [B, C])`.
-
-This did not come up previously as there was little reason to explicitly
-provide ttype arguments. They are implicit for functions and there is very
-little use case for a ttype on a struct or union.
+	forall(T, Us...)
+	void function(T head, Us tail) {}
+
+	forall(T, Us...)
+	struct Type {};
+
+	int a;  bool b;  char c;
+	function(a, b, c);
+	function(a, [b, c]);
+	// Doesn't work: Type(int, bool, char) x;
+	Type(int, [bool, char]) x;
+
+The `function` case works either way because the tuple value can be
+restructured if it does not match exactly. The `Type` case though does not
+allow restructuring when the type is passed as a type value. This may be
+the most correct form, but seems surprising compared to the common use.
+
+### Unary Tuple Value Syntax
+
+Unary tuples don't use the standard tuple syntax and one of the two alternate
+syntax options your may use instead doesn't work consistently. Solving both
+of these issues would help with consistency.
 
 ### Syntax Conflict
 
-The tuple syntax conflicts with designators and the new C++-style attribute
+The tuple syntax conflicts with designators and the C23 (C++-style) attribute
 syntax.
 
-	struct S { int a[10]; } = { [2] = 3 }; // [2] looks like a tuple
-	[[ unused ]] [[3, 4]]; // look ahead problem
+	int a[10] = { [2] = 3 };
+
+Here [2] = 3 is an array designator, but has the same syntax as an assignment
+to a tuple of references, it isn't until the resolver determains that 2 is
+not a reference that that case can be ruled out.
+
+	[[ unused ]] [[int, int], int] x;
+
+Here the opening `[[` could be a nested tuple or the beginning of an
+attribute, the parser can't figure out until later.
 
 These conflicts break C compatibility goals of Cforall. Designators had to
 their syntax change and Cforall cannot parse the new attributes.
-
-Although most of this redesign is about the semantics of tuples, but an update
-to tuple syntax that removes these conflicts would improve the compatibility of
-Cforall going forward (and also open up the new attribute syntax for cforall
-features).
+The behaviour of these cases, if they could be parsed, should be unchanged.
 
 Change in Model
 ---------------
 This proposal modifies the existing tuples to better handle its main use
-cases. There are some use cases that are no longer handled, and a new
-struct tuple is added to cover those cases.
-
-The new tuples is even more "unstructured" than before.  New tuples are
+cases. There are some use cases that are no longer handled, so in addition
+to changing the existing "restructured tuples" to "unstructured tuples"
+(or packs) a new "structured tuple" is added in the form of struct tuple.
+
+The new tuples is even more "unstructured" than before. New tuples are
 considered a sequence of types or typed entities. These packs are then unpacked
 into the surrounding context. Put differently, tuples are now flattened as much
@@ -259,5 +286,6 @@
 unstructured tuples no longer support.
 
-Note that the underlying implementation might not actually look like this.
+Note that the underlying implementation might not actually look like this,
+but this is how it should seem to the user.
 
 Changed Features
@@ -265,26 +293,76 @@
 Some of the concrete changes to the features of the language.
 
+### Unstructured Tuple / Pack Type
+
+The evolution of our current tuples (called packs in an attempt to make the
+names more distinct). They work like the current tuples except they are
+always flattened. You might still be able to declare nested tuples, but these
+are not meaningful, they are flattened to a single level and, where
+approprate, is inlined into the sounding content.
+
+	[bool, [char, int], long] x;
+	// Becomes:
+	[bool, char, int, long] x;
+
+	void f(bool a0, [char, [int, long]] a1, float a2);
+	// Becomes:
+	void f(bool a0, char a1_0, int a1_1, long a1_2, float a2);
+
+	[,] f(int a0, [,] a1, [bool,] a2);
+	// Becomes:
+	void f(int a0, bool a2);
+
+This actually means that tuples do not participate in overload resolution
+in the way the do currently. Restructuring is always free because they are
+always reduced to the same form as part of type matching.
+
+Packs are still not object types and do not have lifetime functions. They
+cannot be used as object types, nor as any data type, but they can be still
+used as ttypes.
+
+(Unless they need to have lifetime functions for other features.)
+
 ### Structured Tuple Type
 
-There is a standard library or built-in type named `tuple`, it does not need a
-special syntax to write types or instances. The type definition might need some
-primitive support, but if supported as a regular type would look something like
-this:
+There is a standard library or built-in type named `tuple`, it does not need
+a special syntax to write types or values. The type definition might need
+some primitive support, but if supported as a regular type would look
+something like this:
 
 	forall(Ts...)
 	struct tuple {
-		inline Ts all; // inline all specified fields
+		inline Ts all;
 	};
 
-This type is constructed the same way as most types, a list initializer with
-each tuple argument, and the lifetime functions (construction, assignment and
-destruction) work the same. Field access works two ways, the first is accessing
-the `all` field, effectively converting the structured tuple into an
-unstructured tuple, the other is to use tuple indexing directly on the
-structure as if it is an unstructured tuple.
-
-(If `inline` does not work, just rename all to `get`. It does make things a bit
-longer but has no change in functionality. If the `all` access does not work,
-that is more problematic, and tuple slicing might provide a work around.)
+This type wraps up an unstructured tuple, in this case a pack of members,
+and gives it "edges" and so structure. It also gives tuples an interface
+more like a normal structure type, for the anonymous structure use case.
+
+The struct tuple does have lifetime functions, can use list initializer
+syntax and otherwise be treated as a normal structure. You can use regular
+member access syntax to convert the struct tuple into a unstructured pack,
+writing `object.all`.
+
+The `inline` modifier is a new specialized feature to allow you use tuple
+index expressions directly on the type. With or without inline you should
+be able to chain a tuple index expression onto the member expression, such
+as `object.all.1`. The inline specifier allows you to skip the middle
+and use `object.1`.
+
+More complex operations can usually be preformed by taking the pack out of
+the struct tuple and acting on it. Polymorphic operations only have to go one
+level down to get to base operations, there is no need for recursive
+construction, nor manually coding different sizes of tuple. This should give
+most of the ease of working with a primitive tuple, because effectively you
+are except it has been given fixed edges.
+
+A tuple struct should also be an object type, and let's you pass multiple
+values through a single polymorphic slot.
+
+A note on the naming here, because there are more pieces that need names
+instead of symbols. The name `tuple` follows because that is the common name,
+although this means this is now the default tuple in some sense. The name of
+the pack was picked to work with inline and make the difference between `.0`
+and `.all` clear. (If inline doesn't work then `get` might be a better name.)
 
 ### Type Qualifier Distribution
@@ -330,4 +408,7 @@
 up, that cannot be enforced with two different tuples.
 
+This example doesn't have to be implemented this way because we do have the
+special case operations for these already.
+
 ### Type Packs
 
@@ -371,5 +452,5 @@
 
 For local declarations it works similarly, except the name introduced is
-directly usable as a tuple.
+directly usable as a tuple instead of going through a member access.
 
 	forall(Objects...)
@@ -380,4 +461,47 @@
 	}
 
+### Tuple Pack Restructuring
+
+Implicit restructuring still occurs, but is not considered as part of
+overload resolution. The structure of tuples is ignored, where individual
+tuples begin or end is not considered, just the sequence of types.
+
+This can be viewed as flattening both sides (the arguments/caller and the
+parameters/callee) before type resolution. Both any nested packs and packs
+into any larger context:
+
+	call(false, ['a', [-7,]], 3.14)
+	// Inline Nesting:
+	call(false, ['a', -7], 3.14)
+	// Inline into Context:
+	call(false, 'a', -7, 3.14)
+
+The main context where tuples are inlined are parameter lists, in that you
+can consider a parameter list as a single pack. Return types could be viewed
+in this way, but because they are presented in a single type, they are
+already wrapped in a tuple.
+
+	[int, [bool, char]] f();
+	// Inline Nesting:
+	[int, bool, char] f();
+
+This also happens "after" any polymorphic parameters are instantiated.
+
+Empty packs are also collapsed, logically being removed or replaced with
+void as in the following example:
+
+	// For example, this function:
+	forall(Ts...) Ts example(int first, Ts middle, int last);
+	// With Ts = [,], should not be treated as:
+	[,] example(int first, [,] middle, int last);
+	// But instead:
+	void example(int first, int last);
+
+Or closer to it, there are some slight differences between the nullary tuple
+and void, for instance creating some instances for consistency with the other
+tuple types.
+
+The struct tuple is never implicitly restructured.
+
 ### Tuple Declaration/Deconstruction
 
@@ -386,5 +510,5 @@
 elements of the tuple can be named.
 
-	[int quo, int rem] ret = divmod(a, b);
+	[int quo, int rem] quorem = divmod(a, b);
 
 Here `ret` refers to the tuple, the entire pack, while `quo` and `rem`
@@ -396,5 +520,8 @@
 no named to access it.
 
-PAB: I do understand the point of this.
+This does not add any new functionality, more it is a qualify of life feature
+making it very easy to give elements of a tuple descriptive names
+instead of trying to combine a name for the whole tuple with an index.
+(`quo` and `rem` vs. `quorem.0` and `quorem.1`)
 
 ### Tuple Casts
@@ -405,44 +532,53 @@
 so it may be replaced with other features (for example: tuple slicing).
 
-### Forbidden Tuples
-
-The unstructured tuple cannot represent all the types that the previous
-semi-structured tuple could. These cases still exist in various ways,
-specifically in the internals of a polymorphic type, but in general should be
-considered in their reduced form.
-
-Forbidding some of these tuples may remove ambiguity and solve some syntax
-conflicts that currently exist.
-
-Nullary, or 0 element tuples, are equivalent to void, the type that carries
-no data, because they do not either. It should either be replaced with void
-or removed entirely when it appears in a larger sequence.
-
-	// For example, this function:
-	forall(Ts...) Ts example(int first, ????)
-	// With Ts = [], should not be treated as:
-	[] example(int first, [] middle, int last);
-	// But instead:
-	void example(int first, int last);
-
-Unary, or 1 element tuples, should be the same as their element type. That
-is to say a single type in an unstructured tuple is a no-op.
-
-Lastly, nested tuples are always flattened to a one-depth tuple.  This means
-that `[bool, [char, int], float]` is resolved as `[bool, char, int, float]`,
-with the internal structure of the tuple ignored.
-
-The flatten into a large sequence rule mentioned above is actually just an
-application of this. Unstructured tuples can already be restructured, even at
-the top level of an function call. This can be expressed by considering the
-argument list as a tuple:
-
-	call(false, ['a', -7], 3.14)
-	call([false, ['a', -7], 3.14])
-	call([false, 'a', -7, 3.14])
-	call(false, 'a', -7, 3.14)
-
-The ability to write nested tuples may remain so tuple deconstruction can be
-used to name a slice of the tuple.
+	// Allowed:
+	([bool, short])tuple_bool_char;
+	([int, float])tuple_float_float;
+
+	// Forbidden:
+	([int, int, int])tuple_int_int;
+	([long, [float, int]])tuple_long_float_int;
+
+### New Tuple Literal Syntax
+
+In addition to the main redesign of this proposal, the syntax is updated to
+be more consistant. It is now a "[]" list with "," separators and a ","/comma
+terminator that is optional for tuples with 2 or more elements (those that
+already have a comma in them) and manditory in other tuples.
+
+It should also be symmetric between types and value, differing only in that
+an element (ITEM below) of a tuple type is a type and the element of a tuple
+value is a value.
+
+-   Nullary Tuple: [,]
+-   Unary Tuples: [ITEM,]
+-   Multiary Tuples: [ITEM, ITEM] [ITEM, ITEM,] [ITEM, ITEM, ITEM] ...
+
+Currently, although syntax is provided to write them, but manually writing
+a nullary or unary tuple should be very rare. This is because a nullary tuple
+can either be erased or treated as void, while unary tuples can be treated
+as their element type. Similary for nested tuples, can be treated as the
+flattened tuple.
+
+(Update: Orignal nullary tuple proposal was `[]`, but that had some issues.)
+
+### TType Argument Syntax
+
+It would be nice to seamlessly provide packs of types in polymorphic
+argument lists, however doing so requires a new restriction.
+
+As an example of the change, consider providing arguments to a polymorphic
+structure with a otype and a ttype parameter.
+
+	forall(T, Us...) struct D {...};
+	D(int, [,])            // D(int)
+	D(bool, [char,])       // D(bool, char)
+	D(long, [int, short])  // D(long, int, short)
+
+This is a nice syntaxtic improvement for the common case, it does restrict
+some of the more complex cases, such as cases with two ttypes. There are
+various restrictions on this for functions. If the rules make it unambigous
+then the grouping could be omitted, or a more advanced version, it can be
+ommited only in the indivual cases where it is unambigous.
 
 ### Tuple Slicing (Range Tuple Indexing)
@@ -454,14 +590,14 @@
 index expression to be a list-range a multiple sub-tuples can be extracted.
 
-	[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].0~2,5~9~2
-
-produces the tuple
-
-	[0, 1, 2, 5, 7, 9]
-
-(Note the position and values are the same to simplify the example.) That is,
-index the first 3 tuple elements, and then indexes elements 5 to 9 in steps of
-2. Not all selections are possible with this mechanism (e.g., index the
-Fibonacci elements), but it covers many cases.
+	['a', 'b', 'c', 'd', 'e', 'f'].0~3
+	['a', 'b', 'c', 'd', 'e', 'f'].1~5~2
+	// Produces:
+	['a', 'b', 'c']
+	['b', 'd']
+
+In words, the first indexes the first 3 tuple elements (0, 1, 2, stopping
+before index 3) and the second indexes elements starting at index 1, stoping
+before index 5 going in steps of 2. This does not allow for arbitary
+selections, but it covers many common slices.
 
 To get the new tuple, the range has to be constructed and traversed at compile
@@ -486,9 +622,7 @@
 The iterators proposal has a section on some new range types, this feature
 is intended to be built on that feature. Not simply reuse some of the syntax
-that is also used in the special for loop. And compile-time evaluation may
-need to be improved.
-
-PAB, I don't understand this last part as the index range is compile time not
-runtime.
+that is also used in the special for loop. This may add some requirements
+about the compile-time evaluation on range expressions to make sure these
+expressions can be evaluated at compile-time.
 
 Implementation
@@ -496,29 +630,120 @@
 An overview of the implementation details of the new proposal.
 
-### Structured Tuple Implementation
-
-Under the hood, unstructured tuples are implemented as structured tuples, with
-the restructuring code inserted wherever needed.  In short, the base
-implementation should stay mostly the same.
-
-PAB: The current implementation does not use convert unstructured tuples to
-structured tuples. Look at the code generated for
-
-	int x, y;
-	[x, y] = 3;
-	[x, y] = [y, x];
-
-
-Actually inlining tuples can be done in some cases, it may even help with
-some forms like a fixed tuple decomposition. However, polymorphic tuples
-still need to be reduced to a single generic form, which would be a
-polymorphic container, a tuple.
+### Structured Tuple
+
+There is actually a decision point here. If it can be implemented entirely
+in the standard library, that would be good. If it cannot, it can actually
+be implemented as the same primitive implementation as we use now and may be
+how unstructured tuple packs are implemented.
+
+### Member Pack Implementation
+
+Implementing member packs can use the same pattern as current built-in tuple
+syntax. This is a two stage process, first is by ... then the it can be
+handled by the existing code for polymorphic but not variadic structures.
+
+	forall(Ts...)
+	struct tuple {
+		Ts get;
+	};
+
+So when used with diffences length an hidden declaration is created which
+has the pack parameter replaced with the approprate number of object type
+parameters. Such as in the following examples:
+
+	struct tuple$0 {
+	};
+
+	forall(Ts$0)
+	struct tuple$1 {
+		Ts$0 get$0;
+	};
+
+	forall(Ts$0, Ts$1)
+	struct tuple$2 {
+		Ts$0 get$0;
+		Ts$1 get$1;
+	};
+
+Then it can be handled by the regular boxing code. Detection of these cases
+will have to changed because it is no longer a single case. But the pattern
+does work if the structure has additional fields in it, as they are just
+placed before and after the pack.
+
+	forall(U, Ts...)
+	struct blob {
+		int header;
+		Ts data;
+		U footer;
+	};
+
+	forall(U, Ts$0, Ts$1)
+	struct blob$2 {
+		int header;
+		Ts$0 data$0;
+		Ts$1 data$1;
+		U footer;
+	};
+
+The `inline` member pack just effects the resolver. It should be expanded out
+to the member access and then the tuple index expression.
+
+### Local Declaration Pack
+
+Packs of local declarations can be handled very differently if they are
+concrete or not. Concrete packs can be writen out in full (even if some
+individual elements are polymorphic) can be inlined directly, expanding out
+into a series of object declarations.
+
+	[A, B] local = func();
+	call(local);
+
+	A local$0;
+	B local$1;
+	?{}([&local$0, &local$1], func());
+	call([local$0, local$1]);
+
+In the polymorphic case though, that entire group needs to be reduced to a
+block that can put into a generic function. Here we can use something like
+the currently existing implementation, where the entire tuple an opaque
+bundle, passed to adapters and thunks for handling.
+
+This is also how tuple declarations are implemented. In the concrete case the
+element names are real and the pack name is replaced with a tuple expression
+of the elements. In the polymorphic case the pack name is real and the
+element names are replaced with tuple index expressions.
+
+### Unstructured Tuple Implementation
+
+Unstructured tuples have two general implementation stratagies. Either they
+are erased and the packs inlined into their context, or they are wrapped
+up as like a structured tuple, generally using the current implementation.
+
+For example, if a concrete pack (size and all the types are known), appears
+in a parameter list the pack can be split and inlined into the argument list.
+
+	void function(int a, [bool, char, short] b, float c);
+	// Becomes:
+	void function(int a, bool b0, char b1, short b2, float c);
+
+On the other hand, if a polymorphic pack appears in the same place, it will
+have to be wrapped up in a dynamic structure so it different instances can
+
+	forall(Ts...)
+	void function(int a, Ts b, float c);
+	// Becomes (after the implicit packing and unpacking operations):
+	forall(T)
+	void function(int a, T* b, float c);
 
 ### AST Updates
 
-The current AST cannot represent all the new features. Particularly, an
-object declaration cannot name elements of the tuple. To this end a new
-node type, `TupleDecl`, should be added to handle tuple deconstruction
-declarations (other cases can still be handled with `ObjectDecl`).
+The AST may already be capable of representing most of this. I have only
+identified one feature that definitely will now work in the current AST, and
+that are the object like tuple declarations with named elements.
+
+Particularly, an object declaration cannot name elements of the tuple.
+To this end a new node type, `TupleDecl`,
+should be added to handle tuple deconstruction declarations
+(other cases can still be handled with `ObjectDecl`).
 
 This would act much like a `FunctionDecl` except for tuples, narrowing the
@@ -527,24 +752,12 @@
 elements of the tuples.
 
-PAB: the following parses:
-
-	[int x, int y] foo( int p );
-
-and discussed by Till.
-
 (I'm not actually going to decide the implementation now, but some early
 examination of the problem suggests that it might be better off wrapping a
 series of `ObjectDecl` rather than just some strings to hold the names.)
 
-### Field Packs
-
-Field packs in structures probably have to be written out in full by the
-specialization pass. If not, it could have some negative effects on layout,
-causing a structure to take up extra space. It may be able to reuse some of the
-specialization code for the existing tuples.
-
 Related Features in Other Languages
 -----------------------------------
-Other languages have similar features. Organized by the related feature.
+Other languages have similar features. Organized by the related feature,
+then language (this does mean we can and do hit languages multiple times).
 
 (In hindsight, I may have gone overboard with the number of examples.)
@@ -584,5 +797,5 @@
 -   https://doc.rust-lang.org/reference/expressions/tuple-expr.html
 
-#### C++ tuple
+#### C++
 
 Implemented as a template type defined in the standard library. No special
@@ -598,19 +811,162 @@
 used, e.g., `std::get<0>( tuple )`.
 
+C++ is an interesting case because it is one of the few cases where no part
+of the tuple system is built-in. It is entirely created in the standard
+library using templates. This also has massive error messages when something
+goes wrong, hopefully our version of struct tuple will reduce the problem.
+
 C++ also has structured binding, a kind of limited pattern matching. In a
-structured binding declaration, you can write an auto typed declaration with
-a list of identifiers in a `[]` list.
-For example, `auto [first, second] = getSize2Tuple();`.
+structured binding declaration, you can write an auto typed declaration where
+a list of identifiers in a `[]` replaces the single identifier.
+
+	auto [first, second] = getSize2Tuple();
+
+The base type has to be `auto` because the base type for each element varies.
+Still, qualifiers (cv and reference) on the auto will be distributed to types
+on the individual members.
+
+The type bound to the binding may be an array, a "plain" structure or any
+type that implements the tuple-like interface (`std::tuple_size` and
+`std::tuple_element`).
 
 -   https://en.cppreference.com/w/cpp/utility/tuple
 -   https://en.cppreference.com/w/cpp/language/structured_binding
 
-PAB: I do not understand the syntax `auto [first, second]`. Where does it come
-from?
-
-#### C++ template
-
-C++ templates can take various types of parameters, including parameter
-packs. These contain series of values. These are used in pack expansion,
+#### Haskell
+
+Haskell has a special syntax for tuples, but otherwise they are completely
+normal polymorphic types. Because of this, tuples have a maximum size.
+Haskell (98) supports tuples of up to 15 elements and the standard library
+has functions for tuples of up to 7 elements.
+
+The syntax for tuples is a comma separated list of elements. Either element
+types to create a tuple type, or element values to create a tuple value. The
+context decides among them, such as `(6, "six")` or `(Bool, Char, Int)`.
+
+Also all the elements can be removed, getting an expression like "(,)" or
+"(,,,)", which can be then be used as a function, for a type, or an expression.
+
+Haskell supports pattern matching as the main way to extract values from a
+tuple, although helper functions "fst" and "snd" are provided for field
+access on two element tuples.
+
+Haskell does not have 0 or 1-element tuples. The nil type, written "()" for
+both type and value, is effectively the 0 element tuple. There is also a type
+called "Solo" that is a polymorphic structure with one field and is used as
+the 1-element tuple, but has regular Haskell data-type syntax.
+
+-   https://www.haskell.org/onlinereport/basic.html
+
+#### OCaml
+
+OCaml only supports multi-element (2 or more) tuples.  It does have the `unit`
+type, which has one value, written `()`. Tuple types are written as a '*'
+separated list of types, tuple values are written as ',' separated list of
+expressions. Pattern matching tuples is supported and uses the same syntax as
+values. Parenthesizing these lists is only needed for grouping.
+
+-   https://ocaml.org/docs/basic-data-types#tuples
+
+#### Swift
+
+Swift has tuple types that use the basic parenthesized, comma separated list of
+types or values. It only supports 0 and 2 or more element tuples (the `Void`
+type is an alias for the empty tuple type).
+
+Swift also supports named tuples. Names can be added before the tuple element,
+both for the tuple type and value. The syntax is a name followed by a colon,
+e.g., `(first: int, second: int)`. These names are a fixed part of the type,
+and can be used as part of field access notation (otherwise numbers are used
+in-place of field names `tuple.0` vs. `tuple.first`).
+
+-   https://docs.swift.org/swift-book/documentation/the-swift-programming-language/types/#Tuple-Type
+
+#### Python
+
+In Python tuples are immutable lists. Because they are dynamically typed,
+there is only one tuple type `tuple`.
+
+It also has various named tuples. The first, namedtuple, allows naming the
+elements of the tuple. The second, NamedTuple, is actually a way of creating a
+typed record in a normally untyped language.
+
+-   https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
+-   https://docs.python.org/3/library/collections.html#collections.namedtuple
+-   https://docs.python.org/3/library/typing.html#typing.NamedTuple
+
+#### LISP
+As LISP is dynamically typed, its `cons` data type is an untyped pair and is
+(perhaps infamously) the main constructor of all compound data types.  The
+function `cons` takes two arguments and builds a pair. Functions `car` and
+`cdr` get the first and second elements of the pair.
+
+### Packs
+Packs (or unstructured tuples) are a much less common feature. In fact, there
+might just be one language, C++, that supports packs. The most common use
+case for unstructured tuples is returning multiple values, so there is a
+comparison to languages that have that as a special feature.
+
+#### Go
+Go does not have built in tuple types, but it has multi-return syntax that
+looks like the tuple syntax of many other languages.
+
+```
+func main() {
+	i, j := returnIntInt()
+	...
+}
+
+func returnIntInt() (int, int) {
+	return 12, 34
+}
+```
+
+Go can unpack multiple return values and pass them all to a function, but
+the unpacked tuple must match the parameter list exactly.
+
+```
+func acceptIntInt(a int, b int) {
+	fmt.Println(a, b)
+}
+```
+
+-   https://golangdocs.com/functions-in-golang
+-   https://go.dev/src/go/types/tuple.go
+
+#### Lua
+Lua is a scripting language that is dynamically typed and stack based. Although
+the stack is usually only directly visible in the C-API, it does allow any
+function to return any number of values, one, zero or more, from any return
+expression.
+
+```
+local funcion f()
+	return 12, 34
+end
+
+local i, j = f()
+```
+
+The last argument in an argument list can be an expression - function call -
+with multiple results and all the results are passed to the function after
+other arguments.
+
+Because Lua is dynamically typed, multiple return values are allowed anywhere
+and the length of the value listed is adjusted, discarding any extra values
+and filling in new values with the value `nil`. This is also used if a
+function is called with the incorrect number of arguments.
+
+-   https://lua.org/
+-   https://lua.org/manual/5.4/manual.html#3.4.12
+
+#### C++
+
+We return to C++ to view template parameter packs. These are the symmetric
+with our pack feature (and both are even used to construct the structured
+tuples in the last section).
+
+C++ template parameter packs are a modification that can be applied to any
+template parameter, so the parameter now takes a series of arguments instead
+of just one. These are used in pack expansion,
 which usually expand to a comma separated list, but it can also be a chain of
 boolean binary operator applications. For example, if the parameter
@@ -643,6 +999,13 @@
 
 There are also fold expressions that use binary operators to combine a pack
-into a single expression. For example, `args + ... + 0` which adds every
-element of the `args` pack together.
+into a single expression. For example, you can write a variadic sum function
+that compiles down to the primitive additions.
+
+```
+template<typename... Args>
+int sum(Args&&... args) {
+	return (args + ... + 0);
+}
+```
 
 C++ is about the best you could ask for in this area, but it does a lot of work
@@ -652,108 +1015,2 @@
 -   https://en.cppreference.com/w/cpp/language/parameter_pack
 -   https://en.cppreference.com/w/cpp/language/fold
-
-#### Haskell
-
-Haskell has a special syntax for tuples, but otherwise they are completely
-normal polymorphic types. Because of this, tuples have a maximum size.
-Haskell (98) supports tuples of up to 15 elements and the standard library
-has functions for tuples of up to 7 elements.
-
-The syntax for tuples is a comma separated list of elements. Either element
-types to create a tuple type, or element values to create a tuple value. The
-context decides among them, such as `(6, "six")` or `(Bool, Char, Int)`.
-
-Also all the elements can be removed, getting an expression like "(,)" or
-"(,,,)", which can be then be used as a function, for a type, or an expression.
-
-Haskell supports pattern matching as the main way to extract values from a
-tuple, although helper functions "fst" and "snd" are provided for field
-access on two element tuples.
-
-Haskell does not have 0 or 1-element tuples. The nil type, written "()" for
-both type and value, is effectively the 0 element tuple. There is also a type
-called "Solo" that is a polymorphic structure with one field and is used as
-the 1-element tuple, but has regular Haskell data-type syntax.
-
--   https://www.haskell.org/onlinereport/basic.html
-
-#### OCaml
-
-OCaml only supports multi-element (2 or more) tuples.  It does have the `unit`
-type, which has one value, written `()`. Tuple types are written as a '*'
-separated list of types, tuple values are written as ',' separated list of
-expressions. Pattern matching tuples is supported and uses the same syntax as
-values. Parenthesizing these lists is only needed for grouping.
-
--   https://ocaml.org/docs/basic-data-types#tuples
-
-#### Swift
-
-Swift has tuple types that use the basic parenthesized, comma separated list of
-types or values. It only supports 0 and 2 or more element tuples (the `Void`
-type is an alias for the empty tuple type).
-
-Swift also supports named tuples. Names can be added before the tuple element,
-both for the tuple type and value. The syntax is a name followed by a colon,
-e.g., `(first: int, second: int)`. These names are a fixed part of the type,
-and can be used as part of field access notation (otherwise numbers are used
-in-place of field names `tuple.0` vs. `tuple.first`).
-
--   https://docs.swift.org/swift-book/documentation/the-swift-programming-language/types/#Tuple-Type
-
-#### Python
-
-In Python tuples are immutable lists. Because they are dynamically typed,
-there is only one tuple type `tuple`.
-
-It also has various named tuples. The first, namedtuple, allows naming the
-elements of the tuple. The second, NamedTuple, is actually a way of creating a
-typed record in a normally untyped language.
-
--   https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
--   https://docs.python.org/3/library/collections.html#collections.namedtuple
--   https://docs.python.org/3/library/typing.html#typing.NamedTuple
-
-#### LISP
-As LISP is dynamically typed, its `cons` data type is an untyped pair and is
-(perhaps infamously) the main constructor of all compound data types.  The
-function `cons` takes two arguments and builds a pair. Functions `car` and
-`cdr` get the first and second elements of the pair.
-
-### Packs
-Packs (or unstructured tuples) are a much less common feature. In fact, there
-might just be one language, C++, that supports packs. The most common use
-case for unstructured tuples is returning multiple values, so there is a
-comparison to languages that have that as a special feature.
-
-#### Go
-Go does not have built in tuple types, but it has multi-return syntax that
-looks like the tuple syntax of many other languages.
-
-```
-func main() {
-	i, j := returnIntInt()
-	...
-}
-
-func returnIntInt() (int, int) {
-	return 12, 34
-}
-```
-
--   https://golangdocs.com/functions-in-golang
--   https://go.dev/src/go/types/tuple.go
-
-#### Lua
-Lua is a scripting language that is dynamically typed and stack based. Although
-the stack is usually only directly visible in the C-API, it does allow any
-function to return any number of values, even a single return, in the return
-expression
-
-```
-local funcion f()
-	return 12, 34
-end
-
-local i, j = f()
-```
