NAME

Emacs::EPL - Protocol implementation and data conversions for Emacs Perl

SYNOPSIS

use Emacs::EPL ':server';
Emacs::EPL::loop;

DESCRIPTION

This module is used internally by epl.el and Emacs::Lisp.

If you use eval to catch errors in Lisp functions, and $@ contains a string beginning with '.Emacs::EPL' (note initial dot), be sure to die with the same string before returning control to Lisp.

Protocol State Transition Table

This stuff is mainly for the benefit of the author.

NO.   CONSTRAINTS            INITIAL       MSG CLASS    FINAL
----- ---------------------- ------------- ------------ --------------
(1)                          <0>           START        <1>
(2)                          <1>           RAISE        <0>
(3)                          <1>           RETURN       <2,0>
(4)                          <2,0>         RETURN       <0>
(5)                          <2,n>         UNREF        <3,0,n>
(6)                          <2,n>         CALL         <2,n+1>
(7)   n>0                    <2,n>         RETURN       <2,n-1>
(13)                         <3,0,n>       RETURN       <2,n>
(14)                         <3,m,n>       UNREF        <3,m+1,n>
(15)  m>0                    <3,m,n>       RETURN       <3,m-1,n>

The master is defined to be the process that sends the START message. The other process is the slave. It follows by induction from the table that the master sends in states <0>, <2,n> for even n, and <3,m,n> for odd m+n, and that the slave sends in all other states.

Message Classes

START

Initiate communication, e.g. by running a subprocess or opening a connection. The slave, if able, sends either a handshake (RETURN) or an exception (RAISE) in response. If an exception is raised, no further communication is permitted.

frame = 1
CALL

Request to run code. The calling process may be reentered by a subsequent CALL. Our call ends when we receive a RETURN, RAISE, or POP in the same frame or we send a POP in a next inner frame. If we receive a POP and subsequently use RETURN to exit this frame, the value we return will be ignored.

frame += 1
Lisp: funcall
Perl: eval
RETURN

Deliver the response to a CALL request (7), report successful startup (3), or mark the end of a series of UNREF requests (13, 15). Not permitted in a popped frame.

The three meanings could have been given different names: ``return'', ``handshake'', and ``end_unrefs''.

frame -= 1
Lisp: function return
Perl: eval return
RAISE

Return via exception mechanism, i.e., non-locally. RAISE has the same protocol semantics as RETURN, except that it is permitted in popped frames. It is expected that unless the user has taken specific steps (i.e., a "try" block) in the frame being returned to, the recipient will propagate the exception by sending another RAISE with the same or equivalent argument.

frame -= 1
Lisp: signal
Perl: die
POP

Either terminate communication (4), or exit the current frame (11, 12). This also says that we will ignore the argument of a subsequent RETURN from this frame (but will not ignore a RAISE value).

frame -= 1
Lisp: throw, kill-emacs
Perl: exit, any nonlocal jump other than die
UNREF

Send a list of handles that they have given us and that we promise never to use again, so that they may free up some resources. Maybe the resources they free will include references to our stuff, so they may send us some UNREF requests before ending the list with a RETURN. They must not, however, issue any other kinds of requests until they've sent RETURN in this frame.

frame += 1
Lisp: perl-free-ref, whatever garbage-detection means is in effect
Perl: DESTROY

Thoughts

Mark-and-sweep garbage collection could be supported by:

(16)                         <2,n,@s>      GC           <4,n,@s>
(17)                         <4,n,@s>      RETURN(0)    <2,n,@s>
(18)                         <4,n,@s>      RETURN(1)    <5,0,n,@s>
(19)                         <5,0,n,@s>    RETURN       <3,0,n,@s>
(20)                         <5,m,n,@s>    MARK         <5,m+1,n,@s>
(21)  m>=1                   <5,m,n,@s>    RETURN       <5,m-1,n,@s>

Transition (17) gives the receiver a chance to refuse to support mark-and-sweep or simply to indicate that all references are in use. Which of these two is the case could be indicated by another return code.

It might be useful to distinguish between recursive and nonrecursive calls:

(22)                         <2,n>         SIMPLE_CALL  <6,n>
(23)                         <6,n>         RETURN       <2,n>

Further state classes could be introduced to allow UNREF, GC, RAISE, or POP operations during nonrecursive calls. Better yet, add some boolean parameters to the states we've got and to CALL.

Hey, how about CALL/CC and START_THREAD. Then of course you'd need JOIN, YIELD, LOCK, WAIT, ... . Pretty soon you'd have yourself an operating system. Yawn.

The current EPL implementation uses only transitions of types (1) to (15).

COPYRIGHT

Copyright (C) 2001 by John Tobey, jtobey@john-edwin-tobey.org. All rights reserved.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307  USA

SEE ALSO

Emacs::Lisp, Emacs.