I have put together a handy emacs/guile interaction package built on top of ilisp. I wouldn't doubt, however, that someone on the list has something better. If so, I'd like to try it out. Russell D. McManus Goldman, Sachs & Co. Intl. Equities Technology 8<------------------------------------------------------------------->8 karlheg@inetarena.com (Karl M. Hegbloom) writes: > >>>>> "Russ" == Russ McManus writes: > > Russ> In my experience, the quickest way to do something like this > Russ> is to expose a 'C-ish' interface to Scheme using hand coded > Russ> primitives. I use some elisp to make this quick and > Russ> painless. What I mean by 'C-ish' is stuff like returning -1 > Russ> on error, and setting a global var to the error value. > > Will you please post that elisp? I'd really like to see how you do > it. Ok. The elisp I use is part of my guile interaction package, which is not well modularized :-( You can cut and paste to your heart's desire. The motivating idea is that almost all the work of writing a new primitive is in doing the run time type checking of the supplied arguments. (This is really only true if you follow my earlier suggestion about first exposing a 'C-ish' interface to Scheme, and then providing a proper Scheme interface on top of that.) I find it's easier to do as little as possible in 'C' anyway. The code assumes that you've told Emacs about your new type. Once that is done, you use an interactive function to describe the arguments to your new primitive, and then Emacs inserts the skeleton of the primitive into the current buffer at point. Perhaps an example is in order. Lets say that I define a new Scheme data type (smob) called a channel. I have a type testing function that looks like this: /* beware code straight from memory */ static int channel_p(SCM obj) { return(SCM_NIMP(obj) && SCM_CAR(obj) == g.channel_type_tag); } Then I let Emacs know about this new type with the following forms: (guile-new-type "channel") ;; define a new type (guile-type-property-set ;; tell Emacs how to type test this type "channel" 'pred-fn (function (lambda (str) (concat "exec_p(" str ")")))) Now I can do: M-x guile-insert-primitive Which interactively asks me for the name and type of each argument to the new primitive. So if I defined a new primitive called "snk-open" with arguments "channel" of type "channel", "source-name" of type "string", and "item-name" of type string, Emacs would generate a call to guile-insert-primitive that looks like this: (guile-insert-primitive "snk-open" (quote (("channel" . "channel") ("source-name" . "string") ("item-name" . "string")))) The string inserted into the buffer looks like this: SCM_PROC(s_snk_open, "snk-open", 3, 0, 0, scm_snk_open); static SCM scm_snk_open(SCM channel, SCM source-name, SCM item-name) { SCM_ASSERT(exec_p(channel), channel, SCM_ARG1, s_snk_open); SCM_ASSERT(SCM_NIMP(source-name) && SCM_STRINGP(source-name), source-name, SCM_ARG2, s_snk_open); SCM_ASSERT(SCM_NIMP(item-name) && SCM_STRINGP(item-name), item-name, SCM_ARG3, s_snk_open); } I didn't have to remember how to do type tests, or the format to SCM_ASSERT, or anything else for any of this, which is the whole idea. A few interesting thing to point out. I didn't use th gh_ interface, for no particularly good reason. The generated code could just as easily use gh_. With one exception (oops), the registration of the primitive into the interpreter. With my code, I am using the same mechanism as is used in the guile source itself, which has the advantage of keeping the registration physically next to the primitive definition. If you use the gh_ registration function, there is no obvious way to know where to insert the registration code. Enough baloney. Now for some elisp (it's been posted before, but I'll post it again):