[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Dynamic modules: emacs-module.c and signaling errors

From: Eli Zaretskii
Subject: Re: Dynamic modules: emacs-module.c and signaling errors
Date: Thu, 26 Nov 2015 17:41:25 +0200

> From: Stefan Monnier <address@hidden>
> Date: Wed, 25 Nov 2015 16:19:37 -0500
> I'll just mention that having to learn a whole new way to run Elisp
> functions when writing module code instead of core code just
> sucks rocks!
> It presumes Emacs modules are mainly written by non-Emacs developers.
> And it makes it harder for module writers to graduate to
> Emacs contributors.

I agree that having an entirely different paradigm would be
sub-optimal, to say the least.  But I don't quite see it happening in
this case.

What are the main differences between writing core C code and module C
code?  Here's what I see:

  . The need to call Emacs functions via a pointer.

    IOW, instead of calling, say, 'intern', you need to call
    'env->intern' instead.

    This is not a terrible pain, IMO, and we could make it even less
    so, with 2 measures:

    - Make all the functions in the API have the same names as their
      Emacs siblings.

      Most of them already are; for the rest, we could change the
      names, so that, e.g., vec_size is called ASIZE and vec_set is
      called ASET.

    - Have emacs-module.h define macros that would eliminate the
      'env->' part altogether, so that you can just call 'intern',
      'ASET', etc.

  . Lisp objects are declared as 'emacs_value' instead of

    Once again, we could rename the 'emacs_value' typedef to, say,
    'module_Lisp_Object' or some such.  (I don't recommend using
    'Lisp_Object', because IMO we should make the distinction

  . You cannot freely assign Lisp objects.

    IOW, instead of this:

     Lisp_Object foo = Vsome_variable;

    you need to do this:

     emacs_value foo = env->intern (env, "some-variable");

    and similarly with function calls:

     emacs_value bar = env->funcall (env, env->intern (env, "list"), 3, args);

    But again, with some minimal syntactic sugar, like

     emacs_value Qlist = env->intern (env, "list");

    you can almost have the core syntax back.  And uses of Vfoo in the
    core is possible because we do

     Vfoo = intern ("foo");

    in the initialization code; modules could do the same in their
    init function, and then they'll have this sugar as well.

  . A different (and somewhat awkward) way of doing the equivalent of
    DEFUN and 'provide'.

    I think we should have macros MODULE_DEFUN and MODULE_PROVIDE for
    this.  They are straightforward to write.  I don't think it's
    reasonable to ask each module author to invent the code one can
    see near the end of mod-test.c, it's fairly boilerplate, and will
    most probably be present in any module hence.

  . Signaling an error and 'throw'

    Once again, we should wrap them into convenient macros that look
    similar enough to a call to xsignal or Fthrow.

Are there any other problems?

Maybe you are thinking about emacs-module.c itself.  It does include
some fairly arcane code that is meant to support what was deemed as a
safer interface.  But emacs-module.c is a small file, so I think we
can sustain its somewhat unusual techniques, especially if we add
there a commentary with detailed rules for how each function there
should be written.

> Not to mention that it makes the interface between Emacs modules and
> Emacs core less efficient.

Maybe I'm missing something, but I don't see it that way.  The
interface between the core and a module is the normal Lisp
interpreter; once the module's functions and global variables are
registered, they are just normal Lisp functions and variables.  Is
this incorrect?

The module implementation itself is indeed slightly less efficient
than if we'd code the same functionality directly in core.  But so
what? it's still very close to raw C efficiency, and paying a small
price for the extensibility is well worth it, I think.

> > The alternative is also error-prone though.  It's very easy to forget
> > that some cleanup is needed;
> The alternative is what we use inside Emacs core.  Maybe it's not
> perfect but it worked fine for the last 30 years, with interfaces to
> fairly varied libraries, like libX11, libxml2, libgnutls, ...
> I think it has a pretty good track record.

That's not really an alternative, as doing that means you'd need to
recompile Emacs after adding code to core.

The real question is: what is the alternative _interface_ between
Emacs and the modules that would look like what we do with GnuTLS
etc.?  Do you mean we should have exported all the internal Emacs
functions, and let modules call them directly?  Or do you mean
something else?  IOW, you'd have to present a fairly complete
alternative design, before we could be able to discuss an alternative.

And all those libraries you've mentioned don't need any cleanup when
application code longjmp's.  So this, too, will have to be part of any
alternative design.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]