emacs-devel
[Top][All Lists]
Advanced

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

Re: Dynamic loading progress


From: Stephen Leake
Subject: Re: Dynamic loading progress
Date: Mon, 16 Mar 2015 13:02:16 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.4 (windows-nt)

Aurélien Aptel <address@hidden> writes:

> I've tried to implement modules using Daniel's plan. It turned out to
> be pretty easy, mostly because I'm more familiar with the Emacs
> codebase now and because it's a lot less intrusive than my previous
> attempt.
>
> It's not finished but I have a basic module working on linux. It's a
> proof of concept, basically.

I've implemented a test module that calls two Ada mode parser actions
(see below).

The real module will call the actual parser and build the action args
from the parse results.

I did not have to modify anything in the Emacs C code to make this work,
so it shows this module design is adquate for my use case so far.

I still need to implement the lexer level, which will either need to
call the current elisp lexer, or access the buffer text directly.

Any comments on the coding style? I don't think I need GCPRO on any of
the static emacs_values, because they are all declared at global level
in elisp.

--
-- Stephe


/*

  Emacs module for Ada mode, providing a fast generalized LALR parser

*/

#include <emacs_module.h>

int plugin_is_GPL_compatible;

/* elisp functions */
static emacs_value aref;
static emacs_value cons;
static emacs_value length;
static emacs_value nil;
static emacs_value set;
static emacs_value symbol_value;
static emacs_value vector;
static emacs_value wisi_containing_action;
static emacs_value wisi_statement_action;

/* variables */
static emacs_value wisi_tokens;

/* array of symbols used in grammar actions */
static emacs_value* ada_grammar_names;

static emacs_value Fcons (emacs_env *env, emacs_value a, emacs_value b)
{
  emacs_value args[] = { a, b };

  return env->funcall (env, cons, 2, args);
}

/* Parse BUFFER, using parser in current module. */
static void parse (emacs_env *env, emacs_value buffer)
{
  /* For now, just execute the actions from parsing second line in:
     procedure Foo is
     begin
     A := 1;
     end Foo;

     ada_grammar.adb assignment_statement_0
     wisi-tokens: [(name 24 . 25) (COLON_EQUAL 26 . 28) (expression 29 . 30) 
(SEMICOLON 30 . 31)]
     action: (wisi-statement-action [1 statement-start 2 statement-other 4 
statement-end])
  */

  /* Set `wisi-tokens'; wisi-tokens is let-bound in calling elisp
     function. */

  emacs_value tokens[] =
    {  /* name "A" */
      Fcons (env, ada_grammar_names[245], Fcons (env, env->make_fixnum (env, 
24), env->make_fixnum (env, 25))),

       /* COLON_EQUAL ":=" */
      Fcons (env, ada_grammar_names[ 81], Fcons (env, env->make_fixnum (env, 
26), env->make_fixnum (env, 28))),

       /* expression "1" */
      Fcons (env, ada_grammar_names[194], Fcons (env, env->make_fixnum (env, 
29), env->make_fixnum (env, 30))),

       /* SEMICOLON ";" */
      Fcons (env, ada_grammar_names[ 95], Fcons (env, env->make_fixnum (env, 
30), env->make_fixnum (env, 31)))
    };

  emacs_value args_1[] = { wisi_tokens, env->funcall (env, vector, 4, tokens) };

  env->funcall (env, set, 2, args_1);

  emacs_value pairs[] =
    { env->make_fixnum (env, 1), ada_grammar_names[341], /* statement-start */
      env->make_fixnum (env, 2), ada_grammar_names[342], /* statement-other */
      env->make_fixnum (env, 4), ada_grammar_names[343]  /* statement-end */
    };

  emacs_value args_2[] = { env->funcall (env, vector, 6, pairs) };

  env->funcall (env, wisi_statement_action, 1, args_2);

  emacs_value args_3[] = { env->make_fixnum (env, 2), env->make_fixnum (env, 3) 
};

  env->funcall (env, wisi_containing_action, 2, args_3);

}

/* elisp-callable wrapper for `parse'
   args: BUFFER
*/
static emacs_value Fparse (emacs_env *env, int nargs, emacs_value args[])
{
  parse (env, args[0]);

  return nil;
}

/* Binds NAME to FUN */
static void bind_function (emacs_env *env, const char *name, emacs_value Ffun)
{
  emacs_value Qfset  = env->intern (env, "fset");
  emacs_value Qsym   = env->intern (env, name);
  emacs_value args[] = { Qsym, Ffun };

  env->funcall (env, Qfset, 2, args);
}

/* standard Emacs module init */
int emacs_module_init (struct emacs_runtime *ert)
{
  emacs_env *env = ert->get_environment (ert);

  aref                   = env->intern (env, "aref");
  cons                   = env->intern (env, "cons");
  length                 = env->intern (env, "length");
  nil                    = env->intern (env, "nil");
  set                    = env->intern (env, "set");
  symbol_value           = env->intern (env, "symbol-value");
  vector                 = env->intern (env, "vector");
  wisi_statement_action  = env->intern (env, "wisi-statement-action");
  wisi_containing_action = env->intern (env, "wisi-containing-action");

  wisi_tokens = env->intern (env, "wisi-tokens");

  emacs_value names_1 = env->intern (env, "ada_grammar-names");
  emacs_value args_1[] = { names_1 };
  emacs_value names_2 = env->funcall (env, symbol_value, 1, args_1);
  emacs_value args_2[] = { names_2 };
  int64_t names_length = env->fixnum_to_int (env, env->funcall (env, length, 1, 
args_2));

  ada_grammar_names = malloc (names_length * sizeof (int64_t));

  for (int i = 0; i < names_length; i++)
    {
      emacs_value args[] = {names_2, env->make_fixnum (env, i)};
      ada_grammar_names[i] = env->funcall (env, aref, 2, args);
    };

  bind_function (env, "wisi-module-parse", env->make_function (env, 1, 1, 
Fparse));

  return 0;
}



reply via email to

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