Newsgroups: comp.lang.scheme
Path: cantaloupe.srv.cs.cmu.edu!das-news2.harvard.edu!news2.near.net!news3.near.net!noc.near.net!cambridge-news.cygnus.com!news.cygnus.com!nntp!lord
From: lord@x1.cygnus.com (Tom Lord)
Subject: Re: Scheme->c
In-Reply-To: jdonham@us.oracle.com's message of 21 Jan 1995 02:31:23 GMT
Message-ID: <LORD.95Jan21024534@x1.cygnus.com>
Sender: news@cygnus.com
Nntp-Posting-Host: x1.cygnus.com
Organization: Cygnus Support
References: <3fl3vb$iqa@homer.cs.mcgill.ca> <JDONHAM.95Jan20183123@hadron.us.oracle.com>
Date: Sat, 21 Jan 1995 10:45:34 GMT
Lines: 48





   A closure c is invoked like:

     return = c.func(val, c.f, c.g);

   Of course, for this to be useful, all procedures must be closures, and
   you probably need a general environment mechanism. As the saying goes,
   if you want Scheme you know where to find it :).

   Jake


I agree.  But if you really need to compose functions in C, and
want to get back ordinary C function pointers instead of structures
as above, this is quite possible -- but with constraints.

One way is to write non-portable code to do on-the-fly code generation
of the composed function.  If you know the types of the functions you
will be composing (or can get the compiler to tell you), then very 
little code generation is needed  -- a stock sequence of O(10) instructions
will do the trick.  The key idea is that your sequence can find some
spare register in which to pass a `hidden parameter' to an otherwise
ordinary C function that does most of the work.  The hidden
parameter in this case points to a structure that holds the two
function pointers being composed. 

Another way is to write portable code but put a small upper bound on the
number of composed functions that can exist.  Once again, you have
to know the types of what you will be composing in advance:

	struct compose_data
	{
	   int (*f) (int);
	   int (*g) ();
	} compositions[100];

	...and then 100 copies of this:

	int composed_fn_<n> ()
	{
	   compositions[<n>].f (compositions[<n>].g ());
	}


-t
