Commit | Line | Data |
---|---|---|
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. | |
34 | If @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. | |
39 | If @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 | |
56 | one 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 |
77 | into the current Scheme module. If any @var{imports} are specified, |
78 | they 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 |
94 | the current Scheme module. If any @var{imports} are specified, they |
95 | are 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. | |
109 | Each @var{def} is either an object, in which case that object must be | |
110 | a named procedure or macro and is exported to Elisp under its Scheme | |
111 | name; or a symbol, in which case the variable named by that symbol is | |
112 | exported under its Scheme name; or a pair @var{(obj . name)}, in which | |
113 | case @var{obj} must be a procedure, macro or symbol as already | |
114 | described and @var{name} specifies the name under which that object is | |
115 | exported 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)) |