*** BUG: if I start and stop the video, not on a reconnect, I get a failure
    in connectSend that the outports are not zero.  Things to do:

    1) Make sure this doesn't happen with the old code.  If it does, that
       means I can assume it's not region-based (I'm suspecting this is the
       case).
    2) ...

----------------------------------------------------------------------

One problem is that when I'm creating the components from the compinfos, I
have to create a ConnInfo etc.  A couple of possibilities:

1) Pass around the dynregion handle in the routines that create components.
   The drawback here is that the code is then tied to using dynregions for
   its allocation, and is thus less usable.

2) Create a work list of connections to make, based on the send and recv
   components we have created.  Then we just have to pass a region around to
   create the components, and only in the outer loop do we have to reveal
   that this is a dyn region.

 conn
   |
   v
conntype--------------------------------
   |                      \              \
   v                       v              v
conninfo ---> component  connclass ---> sendinfo
                                        recvinfo

list ---> compinfo

----------------------------------------------------------------------

Would be nice to have XML parser generated non-heap-allocated AST.

To do:
------

3) Try to get the components to live in a dynamic region.
   a) will have to handle ConnInfo etc. in the right way

***Ouch #2.

   More text below, but I need to get Greg to help me figure out how to fix
   the type error I'm getting with inport functions.  The issue is that I
   want to make a closure out of a polymorphic function.

/*----------------------------------------------------------------------*/
/* Component-specific inport closures (to work with `U types) */
struct InportFn<`bd::R> { <`env::B> : regions(`env) > `bd
  int (@`H f)<`r::TR>(`env,streambuff_t<`r,`U>);
  `env env;
};

inportfn_t<`r,`r2>
make_inportfn(region_t<`r2> r,
	      int (@`H f)<`r::TR>(`env,streambuff_t<`r,`U>),
	      `env x : regions(`env) > `r2) {
  return rnew (r) InportFn(f,x);
}

// apply closure f to argument x
int apply_inportfn(inportfn_t f, streambuff_t<`r,`U> x) {
  let &InportFn{<`env> code,env} = f;
  return code(env,x);
}

/** The function used to implement component input ports
 **/
extern struct InportFn<`r::R>;
typedef struct InportFn<`r> @`r2 inportfn_t<`r,`r2>;

extern inportfn_t<`r,`r2> 
make_inportfn(region_t<`r2> r,
	      int (@`H f)<`r::TR>(`env,streambuff_t<`r,`U>),
	      `env x : regions(`env) > `r2);
extern int apply_inportfn(inportfn_t f, streambuff_t<`r::TR,`U> x);

struct Component<`r::R> {
  string_t<`r> id;
  double rate;
  /** [rate] specifies how often a component should be scheduled **/
  inportfn_t<`r> ?`r inports;
  /** [inports] is an array of closures to be called
      by those components that connect to this component.  The
      closures take a frame (plus a hidden environment) as
      their argument.
  **/
  inportfn_t<`r> ?`r outports;
  /** [outports] is an array of closure pointers (each possibly null)
      pointing to inports of other components this component
      is connected to.  Each outport has the same output value,
      and each is "copied" to the corresponding inport.
  **/
  fn_t<inportfn_t<`r> ?`r @,int,`r> schedule_f;
  /** [schedule_f] is the function called at each schedule point,
      which takes the inports and outports as its arguments
  **/
};

   -----------------

   My definition of inport doesn't use 1st class polymorphism.  That is, an
   inport, and therefore a component, is parameterized by the region its
   data lives in.  Thus, when I create the components, I have to pick which
   region.

   The main problem with this is that I can't assume a component can handle
   either unique or non-unique inports/buffers.  I can get around this in
   forwardToComponents by doing run-time checks when cloning??

   However, this has the problem that I can't feed into a single component
   from two components where one sends a `U and the other a `H.

   The other problem is that I can't force components to take TR-kinded
   inputs all the time, because some of them don't work that way.  Again I
   think I need run-time checks.

   Neither case works well if the buffer data is stored in neither the heap
   nor the unique region.

***Ouch.  It looks like my trick with refining the kind of a tvar inside of
   an if is not working.  In particular, the following will fail:

int foo(region_t<`r1> r1, char ?`r1::TR ?`r2::TR buf) {
  if (r1 == Core::unique_region) {
    alias <`r> b = (char ?`r1 ?`r)buf;
    Core::ufree(buf[0]);
  }
}

I think this is because we have distinct syntactic instances of the type
variable r1, and when these are checked by check_type, their kind is fixed.
That is, I believe our code assumes that a particular type variable will
always have the same kind.

***Make sure I can't create the same region twice when aliasing (i.e. that
shadowing works properly).
***Bug: this works:

    char ?NOZEROTERM buf;
    for (int i=0; i<l; i++) {
      buf = NULL;
      buf :=: data[i].buf;
      Core::ufree(buf);
    }

but this doesn't:

    for (int i=0; i<l; i++) {
      char ?NOZEROTERM buf = NULL;
      buf :=: data[i].buf;
      Core::ufree(buf);
    }

this indicates the flow is not being properly updated.

Ick:

Wanted to put components in a DynRegion, but it turns out this pulls in
ConnInfo stuff, since they reference components.  Need to figure out how all
these pieces fit together.

Uniqueness:
- whenever we do a swap, we need something to swap it with.  Oftentimes the
most straightforward thing to swap with is NULL.  However, this forces our
datastructures to be possibly-NULL pointers in general.  One possibility
that I tried was to have the API take in not-null pointers (so the rest of
the program doesn't suffer), and just store possibly-null pointers
internally.  But this doesn't work unless the datastructure you store them
in is const, or else you get the subtyping/ref unsoundness.

Const-polymorphism is once again a big win here.

In mpegcomp.cyc, when I pass a *`U into a function expecting a *`TR, the
value is consumed.  Is there a good reason for this?  In particular, I can
alias the pointer to a `R kinded pointer, and it works.  Perhaps `U is a
special case ... ?

Hashtable: can I make a version of hashtable that uses unique pointers?
Probalby uses lists for chaining, so using unique pointers could be hard.
If I converted to arrays it would be much easier I suspect.  In any case,
when we do create components, we make this hashtable that we summarily
ditch.

Dynamic Regions:
- should allocate components in dynamic regions.  This will be useful on
reconfigurations: when the old configuration is no longer needed, we can
free the whole region that it lives in, create a new region for the new
configuration, and continue.
