eval-elisp uses primitive-eval
[bpt/guile.git] / lang / elisp / interface.scm
CommitLineData
3d1a89b9 1(define-module (lang elisp interface)
39f30ea2 2 #:use-syntax (lang elisp expand)
3d1a89b9
NJ
3 #:use-module (lang elisp internals evaluation)
4 #:use-module (lang elisp internals fset)
5 #:use-module ((lang elisp internals load) #:select ((load . elisp:load)))
e79236a9 6 #:use-module ((lang elisp transform) #:select (transformer))
3d1a89b9 7 #:export (eval-elisp
e79236a9 8 translate-elisp
3d1a89b9
NJ
9 elisp-function
10 elisp-variable
11 load-elisp-file
12 load-elisp-library
13 use-elisp-file
14 use-elisp-library
15 export-to-elisp
16 load-emacs))
17
18;;; This file holds my ideas for the mechanisms that would be useful
19;;; to exchange definitions between Scheme and Elisp.
20
21(define (eval-elisp x)
22 "Evaluate the Elisp expression @var{x}."
cdde57b2
AW
23 (save-module-excursion
24 (lambda ()
25 (set-current-module the-elisp-module)
26 (primitive-eval x))))
3d1a89b9 27
e79236a9
NJ
28(define (translate-elisp x)
29 "Translate the Elisp expression @var{x} to equivalent Scheme code."
30 (transformer x))
31
3d1a89b9
NJ
32(define (elisp-function sym)
33 "Return the procedure or macro that implements @var{sym} in Elisp.
34If @var{sym} has no Elisp function definition, return @code{#f}."
35 (fref sym))
36
37(define (elisp-variable sym)
38 "Return the variable that implements @var{sym} in Elisp.
39If @var{sym} has no Elisp variable definition, return @code{#f}."
40 (module-variable the-elisp-module sym))
41
42(define (load-elisp-file file-name)
43 "Load @var{file-name} into the Elisp environment.
44@var{file-name} is assumed to name a file containing Elisp code."
45 ;; This is the same as Elisp's `load-file', so use that if it is
46 ;; available, otherwise duplicate the definition of `load-file' from
47 ;; files.el.
48 (let ((load-file (elisp-function 'load-file)))
49 (if load-file
50 (load-file file-name)
51 (elisp:load file-name #f #f #t))))
52
53(define (load-elisp-library library)
54 "Load library @var{library} into the Elisp environment.
55@var{library} should name an Elisp code library that can be found in
56one of the directories of @code{load-path}."
57 ;; This is the same as Elisp's `load-file', so use that if it is
58 ;; available, otherwise duplicate the definition of `load-file' from
59 ;; files.el.
60 (let ((load-library (elisp-function 'load-library)))
61 (if load-library
62 (load-library library)
63 (elisp:load library))))
64
65(define export-module-name
66 (let ((counter 0))
67 (lambda ()
68 (set! counter (+ counter 1))
69 (list 'lang 'elisp
70 (string->symbol (string-append "imports:"
71 (number->string counter)))))))
72
39f30ea2
AW
73(define use-elisp-file
74 (procedure->memoizing-macro
75 (lambda (exp env)
76 "Load Elisp code file @var{file-name} and import its definitions
3d1a89b9
NJ
77into the current Scheme module. If any @var{imports} are specified,
78they are interpreted as selection and renaming specifiers as per
79@code{use-modules}."
39f30ea2
AW
80 (let ((file-name (cadr exp))
81 (env (cddr exp)))
82 (let ((export-module-name (export-module-name)))
83 `(begin
84 (fluid-set! ,elisp-export-module (resolve-module ',export-module-name))
85 (beautify-user-module! (resolve-module ',export-module-name))
86 (load-elisp-file ,file-name)
87 (use-modules (,export-module-name ,@imports))
88 (fluid-set! ,elisp-export-module #f)))))))
3d1a89b9 89
39f30ea2
AW
90(define use-elisp-library
91 (procedure->memoizing-macro
92 (lambda (exp env)
93 "Load Elisp library @var{library} and import its definitions into
3d1a89b9
NJ
94the current Scheme module. If any @var{imports} are specified, they
95are interpreted as selection and renaming specifiers as per
96@code{use-modules}."
39f30ea2
AW
97 (let ((library (cadr exp))
98 (env (cddr exp)))
99 (let ((export-module-name (export-module-name)))
100 `(begin
101 (fluid-set! ,elisp-export-module (resolve-module ',export-module-name))
102 (beautify-user-module! (resolve-module ',export-module-name))
103 (load-elisp-library ,library)
104 (use-modules (,export-module-name ,@imports))
105 (fluid-set! ,elisp-export-module #f)))))))
3d1a89b9
NJ
106
107(define (export-to-elisp . defs)
108 "Export procedures and variables specified by @var{defs} to Elisp.
109Each @var{def} is either an object, in which case that object must be
110a named procedure or macro and is exported to Elisp under its Scheme
111name; or a symbol, in which case the variable named by that symbol is
112exported under its Scheme name; or a pair @var{(obj . name)}, in which
113case @var{obj} must be a procedure, macro or symbol as already
114described and @var{name} specifies the name under which that object is
115exported to Elisp."
116 (for-each (lambda (def)
117 (let ((obj (if (pair? def) (car def) def))
118 (name (if (pair? def) (cdr def) #f)))
119 (cond ((procedure? obj)
120 (or name
121 (set! name (procedure-name obj)))
122 (if name
123 (fset name obj)
124 (error "No procedure name specified or deducible:" obj)))
125 ((macro? obj)
126 (or name
127 (set! name (macro-name obj)))
128 (if name
129 (fset name obj)
130 (error "No macro name specified or deducible:" obj)))
131 ((symbol? obj)
132 (or name
e79236a9 133 (set! name obj))
3d1a89b9
NJ
134 (module-add! the-elisp-module name
135 (module-ref (current-module) obj)))
136 (else
137 (error "Can't export this kind of object to Elisp:" obj)))))
138 defs))
139
140(define load-emacs (elisp-function 'load-emacs))