1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 11:50:28 +02:00
guile/lang/elisp/interface.scm
Andy Wingo 39f30ea29d Fix the elisp memoizer code for syncase-in-boot-9
* lang/elisp/interface.scm:
* lang/elisp/internals/lambda.scm:
* lang/elisp/primitives/syntax.scm:
* lang/elisp/transform.scm: Use (lang elisp expand) as the transformer,
  because we really are intending this code for the memoizer and not the
  compiler.

* lang/elisp/expand.scm: A null expander.

* lang/elisp/interface.scm (use-elisp-file, use-elisp-library):
* lang/elisp/transform.scm (scheme): Turn these defmacros into
  procedure->memoizing-macro calls, given that without syncase we have no
  defmacro either.

* lang/elisp/primitives/fns.scm (macroexpand): Comment out, as Scheme's
  macro expander (temporarily on hiatus) won't work with elisp.
2009-04-25 19:09:19 +02:00

137 lines
5.1 KiB
Scheme

(define-module (lang elisp interface)
#:use-syntax (lang elisp expand)
#:use-module (lang elisp internals evaluation)
#:use-module (lang elisp internals fset)
#:use-module ((lang elisp internals load) #:select ((load . elisp:load)))
#:use-module ((lang elisp transform) #:select (transformer))
#:export (eval-elisp
translate-elisp
elisp-function
elisp-variable
load-elisp-file
load-elisp-library
use-elisp-file
use-elisp-library
export-to-elisp
load-emacs))
;;; This file holds my ideas for the mechanisms that would be useful
;;; to exchange definitions between Scheme and Elisp.
(define (eval-elisp x)
"Evaluate the Elisp expression @var{x}."
(eval x the-elisp-module))
(define (translate-elisp x)
"Translate the Elisp expression @var{x} to equivalent Scheme code."
(transformer x))
(define (elisp-function sym)
"Return the procedure or macro that implements @var{sym} in Elisp.
If @var{sym} has no Elisp function definition, return @code{#f}."
(fref sym))
(define (elisp-variable sym)
"Return the variable that implements @var{sym} in Elisp.
If @var{sym} has no Elisp variable definition, return @code{#f}."
(module-variable the-elisp-module sym))
(define (load-elisp-file file-name)
"Load @var{file-name} into the Elisp environment.
@var{file-name} is assumed to name a file containing Elisp code."
;; This is the same as Elisp's `load-file', so use that if it is
;; available, otherwise duplicate the definition of `load-file' from
;; files.el.
(let ((load-file (elisp-function 'load-file)))
(if load-file
(load-file file-name)
(elisp:load file-name #f #f #t))))
(define (load-elisp-library library)
"Load library @var{library} into the Elisp environment.
@var{library} should name an Elisp code library that can be found in
one of the directories of @code{load-path}."
;; This is the same as Elisp's `load-file', so use that if it is
;; available, otherwise duplicate the definition of `load-file' from
;; files.el.
(let ((load-library (elisp-function 'load-library)))
(if load-library
(load-library library)
(elisp:load library))))
(define export-module-name
(let ((counter 0))
(lambda ()
(set! counter (+ counter 1))
(list 'lang 'elisp
(string->symbol (string-append "imports:"
(number->string counter)))))))
(define use-elisp-file
(procedure->memoizing-macro
(lambda (exp env)
"Load Elisp code file @var{file-name} and import its definitions
into the current Scheme module. If any @var{imports} are specified,
they are interpreted as selection and renaming specifiers as per
@code{use-modules}."
(let ((file-name (cadr exp))
(env (cddr exp)))
(let ((export-module-name (export-module-name)))
`(begin
(fluid-set! ,elisp-export-module (resolve-module ',export-module-name))
(beautify-user-module! (resolve-module ',export-module-name))
(load-elisp-file ,file-name)
(use-modules (,export-module-name ,@imports))
(fluid-set! ,elisp-export-module #f)))))))
(define use-elisp-library
(procedure->memoizing-macro
(lambda (exp env)
"Load Elisp library @var{library} and import its definitions into
the current Scheme module. If any @var{imports} are specified, they
are interpreted as selection and renaming specifiers as per
@code{use-modules}."
(let ((library (cadr exp))
(env (cddr exp)))
(let ((export-module-name (export-module-name)))
`(begin
(fluid-set! ,elisp-export-module (resolve-module ',export-module-name))
(beautify-user-module! (resolve-module ',export-module-name))
(load-elisp-library ,library)
(use-modules (,export-module-name ,@imports))
(fluid-set! ,elisp-export-module #f)))))))
(define (export-to-elisp . defs)
"Export procedures and variables specified by @var{defs} to Elisp.
Each @var{def} is either an object, in which case that object must be
a named procedure or macro and is exported to Elisp under its Scheme
name; or a symbol, in which case the variable named by that symbol is
exported under its Scheme name; or a pair @var{(obj . name)}, in which
case @var{obj} must be a procedure, macro or symbol as already
described and @var{name} specifies the name under which that object is
exported to Elisp."
(for-each (lambda (def)
(let ((obj (if (pair? def) (car def) def))
(name (if (pair? def) (cdr def) #f)))
(cond ((procedure? obj)
(or name
(set! name (procedure-name obj)))
(if name
(fset name obj)
(error "No procedure name specified or deducible:" obj)))
((macro? obj)
(or name
(set! name (macro-name obj)))
(if name
(fset name obj)
(error "No macro name specified or deducible:" obj)))
((symbol? obj)
(or name
(set! name obj))
(module-add! the-elisp-module name
(module-ref (current-module) obj)))
(else
(error "Can't export this kind of object to Elisp:" obj)))))
defs))
(define load-emacs (elisp-function 'load-emacs))