mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 11:50:28 +02:00
* 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.
137 lines
5.1 KiB
Scheme
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))
|