#ifndef _tot_h /* The One Type. */
#define _tot_h __FILE__
/* $Id: tot.h,v 1.1 2001-10-17 18:00:20 eddy Exp $ */
#include "status.h"

typedef struct do_s *record;
typedef record (*function)(status *up, record *self, ...);
struct do_s { function how; /* ... private; */ };
/* ->how could be called the type of the record
   it knows what private is, if any.

   Frobbing a record.how changes its type.  Given that it doesn't change its
   size, or the fact that other records may be referencing it, this is not a
   thing to do lightly. */

/* Trinity Of Types

   The three flavours of record I'll actually use (to simplify casting issues):
   what varies is the number of arguments to ->how. */

typedef struct go_s *go;	/* zero */
typedef record (*be)(status *, go);
struct go_s { be how; /* ...; */ };
#define BE(stat, self) ((*((self)->how))(stat, self))

typedef struct get_s *get;	/* one */
typedef record (*ask)(status *, get, record);
struct get_s { ask how; /* ...; */ };
#define ASK(stat, look, up) ((*((look)->how))(stat, look, up))

/* This one's a luxury (one can fake many, but two can fake it better). */
typedef struct bind_s *bind;	/* two */
typedef record (*join)(status *, bind, record, record);
struct bind_s { join how; /* ...; */ };
#define JOIN(stat, com, bi, ne) ((*((com)->how))(stat, com, bi, ne))

/* and the caller should cast the things passed into the macros to the correct
   types when necessary, and think carefully about what that may entail.  I've
   designed them so that you're passing in the things that would need the casts
   ... */

/* and I wanted to use DO but had to call it BE so the type could be be:
   do is a reserved word in C.

   (Example of the advantages of syntactic colouring - as soon as I typed do it
   turned it keyword-coloured and I knew I was going to be in trouble using it
   as a type name ... before I'd repeated the error in lots of other places.)  */



/* So, no, it's not the datatype that makes all this interesting.
   It's the protocols. */


extern go Initialise;
/* Not sure what this will be: the following is what I used to think ... */
/* Right at the beginning of everything, in main:

	status here = { NULL, NULL }, *up = &here;
	bind reg = (bind)BE(up, Initialise);
	if JUDGE(here.how, &here) exit(1);

   after which you have a status, up, to serve as everything else's context.  In
   each module's initialiser, likewise,

	status here = { up->how, NULL };
	bind reg = (bind)BE(&here, Initialise);
	if JUDGE(up->how, &here) return reg;

   Either of these will set here->how to a judge (on success): any status whose
   ->how is this judge is described as `ready'.  At the same time, here->up is
   set to a static status pointer somewhere, about which you don't think.  If
   you're not main, and as long as you don't propagate here->up back to up (on
   success), when you return you'll have forgotten all about it.  But main gets
   hold of a chain to hang its status off, that lets the machine do some handy
   things later ...

   The value returned to reg is the central registration toy.  This is the bind
   to which your module's initialisation is going to pass (up, reg, interface,
   matcher) to register that some of its tools have a way of serving some
   interface: the matcher recognises any record, self, which has one of those
   tools as self->how and passes back a record, rec, for which rec->how(state,
   self, ...) is the right thing to call on self, after the manner of the
   relevant interface, with whatever other arguments that calls for and etc.
   Both the interface and the matcher, here, must be static records: they may,
   however, have allocated things hanging off their private space (which it is
   then the module's responsibility to manage).

   You should not record the value of Initialise->how in anything until *after*
   you have called Initialise: the first time it's called, its ->how changes.
   This will be true of most initialisers.

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

  Revision 1.4  1998/12/29 17:26:01  eddy
  Minor tweaks (sigh).

  Revision 1.3  1998/12/29 17:23:05  eddy
  Pause.

  Revision 1.2  1998/12/28 15:00:37  eddy
  Renamed back to tot, having moved status out into its own files.
  More major upheavals are under way.

  Initial Revision 1.1  1998/12/15 21:57:20  eddy
*/
#endif /* _tot_h */

