@c "chapters/templates.texi"
@c $Id: templates.texi,v 1.1 2007/08/20 00:02:48 fang Exp $

@node Templates
@chapter Templates
@cindex templates

@flushright
@i{Your quote here.}

-- Bjarne Stroustrup
@end flushright

@menu
* Template Terminology::
* Template Forward Declarations::
* Default template values::
* Template Type Equivalence::
* Template Type Parameters::
* Template Template Parameters::
* Template Specialization::
* Partial Ordering of Specializations::
* Template Argument Deduction::
* Template Definition Bindings::
* Template Issues::
* Future of Templates::
@end menu

@c ----------------------------------------------------------------------------
@node Template Terminology
@section Terminology

@emph{Arity} of a template signature is the number of parameters, 
or degrees of freedom.  
Non-template definitions are said to have arity zero.  
Later we will also refer to the arity of template specializations.  
We will use @math{|A|} to denote the arity of a template 
(including specialization).  

@c ----------------------------------------------------------------------------
@node Template Forward Declarations
@section Forward declarations
@cindex template forward declarations
@cindex forwar declaration, template

Not yet supported.  
The idea is to declare only the template signature of an identifier, 
without declaring its ports.  
Much like the following in C++:

@example
template <template <int, class> class>
class my_template_class;
@end example

@noindent
@samp{my_template_class} is a class that takes a 
class that takes an integer and a class as a template argument 
as a template argument.  

@menu
* Template signature equivalence::
@end menu

@c ----------------------------------------------------------------------------
@node Template signature equivalence
@subsection Template signature equivalence
@cindex template signature
@cindex signature equivalence
@cindex equivalent, templates

The formal parameters of a forward signature are allowed to have identifiers, 
which facilitates latter parameters depending on former parameters.  
Forward declarations are equivalent if the prototype name matches (in the
same namespace) and their template signatures are equivalent.  
The following forward declarations are equivalent (in C++):

@example
template <int> class foo;
template <int P> class foo;
template <int Q> class foo;
@end example

However, only the identifiers used in template class @emph{definitions}
may be referenced from within the definition.  

@example
template <int R>
class foo @{
  /* R may be referenced as the first parameter */
@};
@end example

Note that nowhere outside of the definition, 
can template parameters be referenced (just as in C++).  
In \hac, one may declare an instance of a declared but undefined type, 
which may not necessarily contain any named parameters.  

@example
foo<7> bar;
int N = bar.R; // ERROR: no public member named R
@end example

Here is an example of equivalent template signatures:

@example
template <int N, int [N]> ...
template <int N, int A[N]> ...
template <int N, int B[N]> ...
template <int M, int A[M]> ...
template <int M, int B[M]> ...
@end example

In all cases, the first parameter must be named because the second
parmeter depends on the first.  
Since nothing else depends on the second parameter, its name is optional.  
Again, only the parameter names used in the definition 
may be referenced from within the definition.  

The same rules in this section (ripped off of C++) pertain to
process, channel, and datatype template definitions in @HAC{}.

@c ----------------------------------------------------------------------------
@node Default template values
@section Default values
@cindex default template parameters
@cindex default parameter values

In C++, default values can only appear as a suffix formal parameter list.  
In @HAC{}, we allow default values in any position of the formal 
parameter list.  
However, each defaulting argument position in a type reference
must be given a placeholder (a blank space between commas), 
even if it is at the end of the argument list.  


@c ----------------------------------------------------------------------------
@node Template Type Equivalence
@section Type-equivalence
@cindex template type equivalence
@cindex type equivalence, template

@strong{NEW:}
In @HAC{}, there are two subclasses of template parameters:
@emph{strict parameters} are required to be equivalent for type-matching,
whereas @emph{relaxed parameters} are ignored when type matching.  
We refer to the @emph{strict type} of an entity as the 
underlying template type with fully-specified strict parameters, 
disregarding its relaxed parameters.  
The rationale for making this distinction is that frequently, 
one wishes to declare sparse or dense collections of the same 
logical type while allowing some internal variation.  
For example, ROM cells hard-wired to $0$ or $1$ are permitted
in the same collection, and would be templated with one relaxed 
parameter for the cell's value@footnote{
The motivation for this comes from the fact that in CAST, 
environment sources could not be arrayed if they differed in values.}.
The user has the freedom to decide what parameters considered relaxed.  

The proposed syntax for distinguishing the two types of parameters is:

@noindent
@i{template-signature}:
@itemize
@item @t{template} @t{<} @i{strict-parameter-list} @t{>}
@item @t{template} @t{<} @i{strict-parameter-list}@math{_{opt}} @t{>}
	@t{<} @i{relaxed-parameter-list} @t{>}
@end itemize

Both parameter lists are syntactically identical.  
When there are no relaxed parameters, the second set of angle-brackets
may be omitted.  
If there are only relaxed parameters, the first set of angle-brackets
are still required but empty.  


There are two levels of type equivalence.  
Two entities are @emph{collection-equivalent} or @emph{collectible}
if their underlying template type is the same and their 
strict parameters are equivalent, 
but not necessarily their relaxed parameters.  
Two entities are @emph{connection-equivalent} or @emph{connectible}
if they are collectible, their relaxed parameters are equivalent, 
and their public interface (port-for-port) is connectible, i.e., 
the dimensions, sizes, and strict types of the ports are themselves, 
connection-equivalent.  
(Note the recursive definition.)
Connectibility implies collectibility, but not vice versa.  

TODO: denotational semantics

@ignore
@strong{OUTDATED:}
Two templated types are equivalence if and only if:
@itemize
@item They are of the same type class (channel, process,... ), obviously
@item They refer to the same base definition.  
@item The port types and dimensions are type-equivalent.  
@item Their template arguments are equal.  
@end itemize

The third and fourth criteria are not necessary equivalent.  
The ports of a template definition need not depend on template
parameters themselves, as is the case with defining 
cyclic source sequences for a channel.  
@end ignore

@strong{Definition}:
a type is @i{complete} is it is either a strict type, 
or a relaxed type with its relaxed parameters bound.  
Connectible-equivalence is the same as equivalence between complete types.  

@strong{DEBATE:} (Resolved, see above: NEW)
Should the fourth criterion be required for type-equivalence, 
or can we allow non-equivalent template parameters as long as the
ports interface is equivalent?  

Implementation requirement:
type errors must be caught by the end of the create-phase of compilation.

@strong{Definition requirement}:
For a template definition to be well-formed, 
all instances (aliases) local to that definition, including ports, 
must have complete type. 
Note that a given definition template may instantiate a definition
for each set of unique template parameters, some of which may
be meet this requirement, others which may not.  
[Quick examples of valid and invalid definition?]

@strong{Syntax and semantics}:
The basic syntax for explicitly binding instance alias type parameters is:
@itemize
@item @i{instance-reference} @t{<} @i{relaxed-parameter-list} @t{>}
@end itemize

@noindent
The instance-reference may reference a collection of aliases 
(with ranged specification), in which case the same relaxed parameters are
bound to each referenced alias.  
(Technically, member references could be rejected in this context 
because all ports are required to have complete type by construction.)

@strong{Application: Arrays}.
The rationale for introducing relaxed types is to be able to 
declare an array of elements whose members are not identical, 
though their interfaces remain compatible.
The following valid example shows how relax-typed arrays are
declared:

@example
template <pint X><pbool B>
defproc foo(...) @{ ... @}

foo<2> bar[2];
bar[0]<true>;  @i{// bind relaxed parameter}
bar[1]<false>; @i{// bind different relaxed parameter}
@end example

@noindent
Had one of the parameter-binding statements been omitted, 
compilation would eventually result in a error indicating
that the unbound instance had incomplete type.  

@strong{Syntactic sugar.}

@noindent
@t{foo<1> bar<true>;}
is equivalent to
@t{foo<1> bar; bar<true>;}.

@noindent
@t{foo<1> bar<true>(...);}
is equivalent to
@t{foo<1> bar; bar<true>; bar(...)}.

@noindent
@t{foo<1> bar<true>[N];}
is equivalent to
@t{foo<1> bar[N]; bar[0..N-1]<true>;}.

@strong{Aliasing and collection strictness.}
Consider the following declarations:
@t{foo<1><true> bar;} and
@t{foo<1> car<true>;}.
@t{bar} cannot be aliased to @t{car} because the collections
(even though they are scalar) have different strictness.  
Strictly speaking, their respective array types are
@t{foo<1><true>} and @t{foo<1>}, which are not equivalent.
For a well-formed connection between two aliases, 
the collections of the respective aliases must be equivalent, 
@emph{match in strictness}, and the relaxed types
bound to each alias must be equivalent or compatible.  
In other words, members of strictly typed collections (arrays) cannot
alias members of relaxed typed collections.  

@strong{Implicit type binding though connections.}
When two aliases are connected to each other, 
the connection is valid if, 
in addition to their parent collections' types being equivalent, 
one of the following holds:
both aliases are bound to equivalent parameters
or at least one alias has unbound parameters.
When an alias is formed, the relaxed type parameters are
automatically `synchronized,' which effectively binds the type
of aliases through other aliases of bound type.  
[Examples from test suite needed.]

Implementation detail: 
As soon as an instance alias is bound to a type, it is instantiated.  
All (reachable) aliases thereof are also instantiated and recursively
connected.  
Attempts to reference members of type-unbound aliases @emph{can} be
rejected as errors.  
(Theoretically, since the public ports may not depend on relaxed
parameters, such references may not be treated as errors in the future.
It is possible to instantiate the ports before the type is bound, 
however, internal aliases cannot be replayed until the type is bound, 
either explicitly or implicitly.
The current policy is just a conservative approximation of the eventual
operational semantics.)

@strong{Type propagation through ports.}
Since definition members and ports are required to have complete type, 
the relaxed parameters must be propagated from the formal definition
to each instantiating context.  Consider the example:
@example
defproc wrap(foo<1> x) @{
x<false>;
@}
wrap Z;
@end example
@noindent
upon instantiating @t{Z} in the top-level,
@t{Z.x} has type @t{foo<1><false>}.  

@strong{Restrictions}.
Where are relaxed parameters forbidden?
In port specifications, types of ports and their array sizes
may not depend on relaxed parameters, 
i.e. they may only depend on strict template parameters.  
This guarantees that the port interfaces remain the same among
members of a relax-typed array.  
In typedef templates, the canonical type's strict template arguments
may not depend on relaxed parameters.  
(Why not?  Allowing so would give a means of subverting 
template parameter strictness.)
Anywhere else in the body of a definition template, 
relaxed parameters may be used freely, 
within the constraints of the fundamental typing rules.  

When should relaxed template parameters be used?
General guideline: when the port interfaces do not depend on
the said parameters.  

@menu
* Relaxed Template Examples::
@end menu

@c ----------------------------------------------------------------------------
@node Relaxed Template Examples
@subsection Template Examples
@cindex relaxed templates

The following example illustrates how one might describe a ROM array
using relaxed template arguments.

@example
template <> <pbool VAL>
defproc ROMcell(...) @{ ... @}

template <pint X, Y> <pbool V[X][Y]>
defproc ROMarray(...) @{
  ROMcell<> x[X][Y];  @i{// <> is optional}
  @i{// can't reference x[i][j].member yet}
  @i{// because instance types are incomplete}
  (i:X:
    (j:Y: x[i][j] <V[i][j]> (...); )
  )
  @i{// from here, may reference x[i][j].member}
@}

ROMarray <2,3>
    a <@{@{false,true,false@},
      @{true,false,true@}@}>;
@end example

This following example shows how one would declare an array of sources
(like for a test environment):

@example
template <pint N>
defchan e1of (...) @{...@}

template <pint N> <pint M; pint V[M]>
defproc source_e1of (e1of<N> c) @{...@}

e1of<4> C[10];
source_e1of<4> CS[10];  @i{// instances' types are incomplete}
CS[0] <1, @{2@}> (C[0]);  @i{// can complete types and connect}
CS[1] <3, @{2,0,1@}> (C[1]);
CS[2] <2, @{1,0@}> (C[2]);
...
@end example

We could have also declared the array of sources with sparse instantiation, 
as long as the strict template arguments match:
@example
source_e1of<4> CS[0..0];
  @i{// this determines the entire collection's strict parameters}
  @i{// but sets the relaxed parameters for only the indexed range}
CS[0]<1, @{2@}>(C[0]);
  @i{// This binds the relaxed template parameters and connects ports.}
source_e1of<4> CS[1..1];
CS[1]<3, @{2,0,1@}>(C[1]);
source_e1of<4> CS[2..2];
CS[2]<2, @{1,0@}>(C[2]);
...
@end example

[TODO: write section on connection examples]

@c ----------------------------------------------------------------------------
@node Template Type Parameters
@section Type Parameters

@strong{TODO:} This section is in consideration for future extension.  

Up to this point, the template parameters covered are 
@emph{valued} parameters.  
We now introduce @emph{type} parameters.  

Some examples:

@itemize
@item @t{template <datatype D> defproc ...}
@item @t{template <chan C> defproc ...}
@item @t{template <proc P> defproc ...}
@end itemize

@c ----------------------------------------------------------------------------
@node Template Template Parameters
@section Template Template Parameters

Punt, I mean it.  
(What do you think this is, C++?)

@c ----------------------------------------------------------------------------
@node Template Specialization
@section Template Specialization
@cindex template specialization
@cindex specialization, templates

MAJOR PUNT.

Semantic contraint:
The forward declaration of a general template must precede any declaration
of any specialization with the same family (same name).  

Also partial specializations.  

@xref{Template Definition Bindings}, for the complicated issues regarding
template specialization.  

@strong{RESOLVE:}
Should we impose any restrictions on whether or not template definitions
may be specialized, and if so, where?  

For example: forcing all forward declarations of specializations for 
a particular definition family would solve the problem of 
specialization coherence, but would make such a family of definitions
unextendable for future specializations -- not all specializations
can be declared up-front!  
Implementation consideration:
For definition families consisting of only specializations (genericless),
this can introduce a lot of overhead in having to process specializations
irrelevant to a particular compilation unit.  

Impose constraints on definitions, perhaps some invariant constraints and
relations between generic and specialized definitions?  (e.g. contains same
named instances)  But this would unnecessarily restrict variations in
implementation of certain definitions.  

Forward declarations of specializations.  

@strong{RESOLVE:}
Do ports of specialized definitions have to match that of the 
generic template definition?  Members certainly need not.  
What are the implications on argument type-checking?

@c ----------------------------------------------------------------------------
@node Partial Ordering of Specializations
@section Partial Ordering of Specializations

Partial and full specializations for a given template definition
may be defined on a partial order.  
Specializations @math{A} and @math{B} are ordered @math{A < B} if and only if
all template parameters that satisfy @math{A} also satisfy @math{B} and 
@math{|A| < |B|}.  
(In English, ...)
If @math{|A| = |B|}, and @math{A \neq B}, 
then @math{A} and @math{B} are not comparable.  
Examples, please.  

@c ----------------------------------------------------------------------------
@node Template Argument Deduction
@section Template Argument Deduction

Not having to specify every (or any) template arguments.

@c ----------------------------------------------------------------------------
@node Template Definition Bindings
@section Template Definition Bindings

Specialization introduces a whole new aspect of complication to the language.  
When a definition is used to instantiate an object, should it be 
instantiated with the best-fit definition seen?  
In C++, the notion of @emph{point-of-instantiation} is used to 
select the definition.  [cite]
Roughly, it says that only definitions that are available (complete)
before the point in the translation unit are considered for instantiation.  
This introduces potential headaches when different translation units
see different available definitions at different points of instantiation, 
i.e. C++ has no mechanism for enforcing consistent use of specializations
across translation units.  
The benefit of compile-time binding of definitions is that type-checking
of template definitions and uses may be done entirely at compile-time
per translation unit.  

@HAC{} uses the unroll-phase as the point-of-instantiation for all 
instances, when all instances are bound to their proper definitions.  
The consequence of such a choice is that compile-time type checking
is @emph{very} limited with respect to template definitions.  
[Discuss implementation issues.]

@strong{RESOLVE:}
Should the following example be accepted or rejected (as a compilation unit)?

@example
template <pbool B>
defproc foo() @{ @}

foo<true> bar;
bool b = bar.x;
@end example

What if another compilation unit provides a specialization for 
@t{foo<true>} with a @t{bool} member @t{x}?

Likewise, consider the following similar example:

@example
template <pbool B>
defproc foo(bool b) @{ @}

foo<true> bar;
bool b = bar.x;
@end example

It is conceivable for a specialization to be defined later without
@math{b} as a bool port.  
Should the last connection statement be accepted at compile-time?
If so, does that constrain the specializations that may be introduced later?


@strong{PROPOSAL:}
A separate bind-phase to allow full type-checking of a compilation unit
(perhaps with references to available definition families).  

@strong{IDEA:}
Allow introduction of new template specializations that
@emph{do not interfere} with pre-determined bindings.  
Rationale: many full-specializations are introduced for one-time use and
do not interfere with other instantiations' bindings.  

@emph{Binding} an instantiation to a definition is recursive: i.e.
all members and sub-instances of a bound instantiation must already be bound.  
Implementation issue: bind-if-possible to automatically bind dependent
instantiations.  

Implementation option: eager or early binding to force 
definition binding and thus allow type-checking of a 
compilation unit that uses template definitions.  

@strong{IMPLEMENTATION:}
Is there a need to track the instantiation statements that @emph{used}
particular specializations?  Need to somehow catch inconsistent views
of specializations...

@strong{BOTTOM LINE:}
Type-references to template definitions MUST have a consistent
view of definitions at instantiation (unroll) time.  

@c ----------------------------------------------------------------------------
@node Template Issues
@section Issues

As useful as templates may seem, they can't be thrown together without
expecting some complications in the language.  
We use this section to slap down issues that may arise.  
Once these issues are resolved, the text for their resolutions
belong to some sort of ``rationale'' document, possibly
in footnotes or appendices in this language specification.  

@menu
* Relaxed Parameters Issues::
* Template Parameter References::
* Template Specialization Issues::
@end menu

@c ----------------------------------------------------------------------------
@node Relaxed Parameters Issues
@subsection Relaxed Parameters

In a sequential scope, an instance of relaxed type
may have its relaxed actuals bound at any time (but once only).  
This means that at the time of unbound instantiation (during unroll), 
the relaxed parameters will not be available for use with unrolling.
However, at the point of instantiation, the public ports
of the instance (which should never depend on relaxed parameters)
should be made available for connections.  
Q: how do we unroll ports in this situation?
Q: do we need to worry about internal aliases differing between
difference different complete types?  Perhaps not because internal
aliases @emph{should} be replayed at create-time before
finalizing footprints.  

@c ----------------------------------------------------------------------------
@node Template Parameter References
@subsection Template Parameter References

PUNTED.  (This is groundwork for template metaprogramming.)

Given a templated definition, such as

@example
template <pint N> defproc foo(...) @{ ... @}
@end example

should the parameter @t{foo::N} be accessible to the programmer
as an rvalue?
If not, then should we allow references to internal member values
(that may be copies of actual parameters)?

@example
template <pint N> defproc foo(...) @{ pint _N = N; @}
pint M = foo<3>::_N;
@end example

Should all internal meta-values be publicly accessible as rvalues?
Allowing access to such variables is the root of the template
metaprogramming paradigm in C++.  

Forbidding direct references to the template parameters may 
inconvenience a programmer by having to explicitly copy-propagate
all parameters that she wishes to export.  
It also avoids any issues that arise with @emph{forward declarations}
and @emph{typedefs templates}.  

Consider the template signature equivalence examples from
@ref{Template Type Equivalence}.  
Among a set of equivalent forward declarations, which set
would be used for lookup?  The first? or last?  
The best answer might be `none': parameters may only be referenced
if the complete definition is available.  

(Looking forward to the chapter on typedefs...)
Now consider the following typedef declaration, continuing from
our previous example:

@example
template <pint N> typedef foo<N+1> goo;
pint P = goo<3>::N;
@end example

@t{goo} has its own parameter N that `shadows' the base definition's
parameter of the same name.  
(Whatif @t{goo}'s parameter was renamed to not collide?
Then @t{goo<3>::N} would clearly have to refer to @t{foo}'s N.)  
Either way this is disambiguated, the meaning would not necessarily be 
intuitive.  
We should simply forbid direct references to template parameters.  

@strong{Proposal:} I am in favor of (what I just said above)

@c ----------------------------------------------------------------------------
@node Template Specialization Issues
@subsection Template Specializations

Should we allow specializations (in the C++ sense)?

Introduces a whole set of issues with binding of dependent names
vs. non-dependent names.  

@c ----------------------------------------------------------------------------
@node Future of Templates
@section Future

Compile-time checking of templates, directives.  

@c ----------------------------------------------------------------------------
