#ifndef _register_h	/* Interfaces and Registration */
#define _register_h __FILE__
/* $Id: register.h,v 1.1 2001-10-17 18:00:20 eddy Exp $ */
#include "chain.h"

extern bind Register;
/* JOIN(status, Register, interface, registrationtool)

   The last argument must be a static regchain record (see below) and nothing
   should ever mess with (even look at) its ->next field. */

typedef struct reg_s regchain;
typedef record (*regfn)(status *up, regchain *self, record interface, record regtool);
/* If a regfn is given an interface for which it is not responsible, it frobs
   up->up.  Otherwise, it registers regtool as an implementation of that
   interface: if this fails it frobs both up->up and up->how, but more usually
   it will succeed and leave up alone.

   The documentation of interface should tell you what kind of regtool it is
   expecting when compilation units register their support of the interface: in
   the case of Register, it should be a (pointer to a) static regchain record.
*/
struct reg_s {
  regfn how;		/* Ignores next, manages private (if any). */
  regchain *next;	/* Register manages this: do not touch ! */
  /* ...;	private fields according to the whim of ->how. */
};

/* A compilation unit defining a `type' has to have a way of registering the
   type's support of interfaces.

   Registration is itself an interface, of course: and an interface has to have
   a way of registering, with the registration interface, the machinery to be
   used for registering support of the interface.  Naturally, Register's own
   support of Register is there at the outset ...

   An interface, eg Add, is a record of a kind having its interface: one can ask
   for JOIN(stat, Add, this, that) to get `this + that'.  So Add has to maintain
   a lookup in which it can find the tool for adding this to that.  Being a JOIN
   interface, it might also use a `reverse' lookup form, but this will be `under
   the bonnet'.  In particular, Register won't have a reverse lookup interface,
   though it will be used to administer the registration of reverse lookup
   interfaces, where defined.

   An implementation, addmine, of the Add interface would have the same, JOIN,
   form as Add: JOIN(stat, addmine, this, that) will return `this + that', with
   stat happy, if this and that are of the right kinds for addmine; otherwise,
   it'll leave stat unhappy and the Add interface will go on to try its next
   putative implementation (or give up, if this means it's run out).

   The Add interface's registration tool, regadd, will want to be given addmine
   and add it to its notional `chain' of things to try (but this chain might be
   some kind of double-keyed dictionary, of course: or something weirder).  Now
   regadd is a registration tool - i.e. an implementation of Register - so it
   will be being called by Register as one of *its* attempts at registering
   addmine as an implementation of Addition.  Thus regadd also needs to be given
   an argument which is the interface with which Register is trying to do its
   registration: it'll return unhappy if that interface isn't Add.  This makes
   regadd, hence Register, a JOIN which takes an interface and a registration
   tool.

   JOIN(stat, Register, Register, regadd) registers regadd as a registration
   tool: JOIN(stat, Register, Add, addmine) registers addmine as an addition
   tool (by calling regadd).

   Register expects regadd to be a static bindchain record and adds it to its
   private chain thereof.  It relies on nobody messing with their registration
   records' ->next fields !

*/

/*
  $Log: register.h,v $
  Revision 1.1  2001-10-17 18:00:20  eddy
  added in all files previously missing from RCS

  Revision 1.2  1999/12/06 19:27:05  eddy
  I seem to have changed stuff and am about to embark on a revolution.

  Initial Revision 1.1  1998/12/29 16:59:29  eddy
*/
#endif /* _register_h */

