store macro definitions in the function slot
[bpt/guile.git] / module / language / elisp / compile-tree-il.scm
1 ;;; Guile Emacs Lisp
2
3 ;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4
5 ;; This program is free software; you can redistribute it and/or modify
6 ;; it under the terms of the GNU General Public License as published by
7 ;; the Free Software Foundation; either version 3, or (at your option)
8 ;; any later version.
9 ;;
10 ;; This program is distributed in the hope that it will be useful,
11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ;; GNU General Public License for more details.
14 ;;
15 ;; You should have received a copy of the GNU General Public License
16 ;; along with this program; see the file COPYING. If not, write to
17 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 ;; Boston, MA 02111-1307, USA.
19
20 ;;; Code:
21
22 (define-module (language elisp compile-tree-il)
23 #:use-module (language elisp bindings)
24 #:use-module (language tree-il)
25 #:use-module (system base pmatch)
26 #:use-module (system base compile)
27 #:use-module (srfi srfi-1)
28 #:use-module (srfi srfi-8)
29 #:use-module (srfi srfi-11)
30 #:use-module (srfi srfi-26)
31 #:export (compile-tree-il))
32
33 ;;; Certain common parameters (like the bindings data structure or
34 ;;; compiler options) are not always passed around but accessed using
35 ;;; fluids to simulate dynamic binding (hey, this is about elisp).
36
37 ;;; The bindings data structure to keep track of symbol binding related
38 ;;; data.
39
40 (define bindings-data (make-fluid))
41
42 ;;; Store for which symbols (or all/none) void checks are disabled.
43
44 (define disable-void-check (make-fluid))
45
46 ;;; Store which symbols (or all/none) should always be bound lexically,
47 ;;; even with ordinary let and as lambda arguments.
48
49 (define always-lexical (make-fluid))
50
51 ;;; Find the source properties of some parsed expression if there are
52 ;;; any associated with it.
53
54 (define (location x)
55 (and (pair? x)
56 (let ((props (source-properties x)))
57 (and (not (null? props))
58 props))))
59
60 ;;; Values to use for Elisp's nil and t.
61
62 (define (nil-value loc)
63 (make-const loc (@ (language elisp runtime) nil-value)))
64
65 (define (t-value loc)
66 (make-const loc (@ (language elisp runtime) t-value)))
67
68 ;;; Modules that contain the value and function slot bindings.
69
70 (define runtime '(language elisp runtime))
71
72 (define value-slot (@ (language elisp runtime) value-slot-module))
73
74 (define function-slot (@ (language elisp runtime) function-slot-module))
75
76 ;;; The backquoting works the same as quasiquotes in Scheme, but the
77 ;;; forms are named differently; to make easy adaptions, we define these
78 ;;; predicates checking for a symbol being the car of an
79 ;;; unquote/unquote-splicing/backquote form.
80
81 (define (backquote? sym)
82 (and (symbol? sym) (eq? sym '\`)))
83
84 (define (unquote? sym)
85 (and (symbol? sym) (eq? sym '\,)))
86
87 (define (unquote-splicing? sym)
88 (and (symbol? sym) (eq? sym '\,@)))
89
90 ;;; Build a call to a primitive procedure nicely.
91
92 (define (call-primitive loc sym . args)
93 (make-application loc (make-primitive-ref loc sym) args))
94
95 ;;; Error reporting routine for syntax/compilation problems or build
96 ;;; code for a runtime-error output.
97
98 (define (report-error loc . args)
99 (apply error args))
100
101 (define (runtime-error loc msg . args)
102 (make-application loc
103 (make-primitive-ref loc 'error)
104 (cons (make-const loc msg) args)))
105
106 ;;; Generate code to ensure a global symbol is there for further use of
107 ;;; a given symbol. In general during the compilation, those needed are
108 ;;; only tracked with the bindings data structure. Afterwards, however,
109 ;;; for all those needed symbols the globals are really generated with
110 ;;; this routine.
111
112 (define (generate-ensure-global loc sym module)
113 (make-application loc
114 (make-module-ref loc runtime 'ensure-fluid! #t)
115 (list (make-const loc module)
116 (make-const loc sym))))
117
118 ;;; See if we should do a void-check for a given variable. That means,
119 ;;; check that this check is not disabled via the compiler options for
120 ;;; this symbol. Disabling of void check is only done for the value-slot
121 ;;; module!
122
123 (define (want-void-check? sym module)
124 (let ((disabled (fluid-ref disable-void-check)))
125 (or (not (equal? module value-slot))
126 (and (not (eq? disabled 'all))
127 (not (memq sym disabled))))))
128
129 ;;; Build a construct that establishes dynamic bindings for certain
130 ;;; variables. We may want to choose between binding with fluids and
131 ;;; with-fluids* and using just ordinary module symbols and
132 ;;; setting/reverting their values with a dynamic-wind.
133
134 (define (let-dynamic loc syms module vals body)
135 (call-primitive
136 loc
137 'with-fluids*
138 (make-application loc
139 (make-primitive-ref loc 'list)
140 (map (lambda (sym)
141 (make-module-ref loc module sym #t))
142 syms))
143 (make-application loc (make-primitive-ref loc 'list) vals)
144 (make-lambda loc
145 '()
146 (make-lambda-case #f '() #f #f #f '() '() body #f))))
147
148 ;;; Handle access to a variable (reference/setting) correctly depending
149 ;;; on whether it is currently lexically or dynamically bound. lexical
150 ;;; access is done only for references to the value-slot module!
151
152 (define (access-variable loc sym module handle-lexical handle-dynamic)
153 (let ((lexical (get-lexical-binding (fluid-ref bindings-data) sym)))
154 (if (and lexical (equal? module value-slot))
155 (handle-lexical lexical)
156 (handle-dynamic))))
157
158 ;;; Generate code to reference a variable. For references in the
159 ;;; value-slot module, we may want to generate a lexical reference
160 ;;; instead if the variable has a lexical binding.
161
162 (define (reference-variable loc sym module)
163 (access-variable
164 loc
165 sym
166 module
167 (lambda (lexical) (make-lexical-ref loc lexical lexical))
168 (lambda ()
169 (mark-global-needed! (fluid-ref bindings-data) sym module)
170 (call-primitive loc
171 'fluid-ref
172 (make-module-ref loc module sym #t)))))
173
174 ;;; Reference a variable and error if the value is void.
175
176 (define (reference-with-check loc sym module)
177 (if (want-void-check? sym module)
178 (let ((var (gensym)))
179 (make-let
180 loc
181 '(value)
182 `(,var)
183 `(,(reference-variable loc sym module))
184 (make-conditional
185 loc
186 (call-primitive loc
187 'eq?
188 (make-module-ref loc runtime 'void #t)
189 (make-lexical-ref loc 'value var))
190 (runtime-error loc "variable is void:" (make-const loc sym))
191 (make-lexical-ref loc 'value var))))
192 (reference-variable loc sym module)))
193
194 ;;; Generate code to set a variable. Just as with reference-variable, in
195 ;;; case of a reference to value-slot, we want to generate a lexical set
196 ;;; when the variable has a lexical binding.
197
198 (define (set-variable! loc sym module value)
199 (access-variable
200 loc
201 sym
202 module
203 (lambda (lexical) (make-lexical-set loc lexical lexical value))
204 (lambda ()
205 (mark-global-needed! (fluid-ref bindings-data) sym module)
206 (call-primitive loc
207 'fluid-set!
208 (make-module-ref loc module sym #t)
209 value))))
210
211 ;;; Process the bindings part of a let or let* expression; that is,
212 ;;; check for correctness and bring it to the form ((sym1 . val1) (sym2
213 ;;; . val2) ...).
214
215 (define (process-let-bindings loc bindings)
216 (map
217 (lambda (b)
218 (if (symbol? b)
219 (cons b 'nil)
220 (if (or (not (list? b))
221 (not (= (length b) 2)))
222 (report-error
223 loc
224 "expected symbol or list of 2 elements in let")
225 (if (not (symbol? (car b)))
226 (report-error loc "expected symbol in let")
227 (cons (car b) (cadr b))))))
228 bindings))
229
230 ;;; Split the let bindings into a list to be done lexically and one
231 ;;; dynamically. A symbol will be bound lexically if and only if: We're
232 ;;; processing a lexical-let (i.e. module is 'lexical), OR we're
233 ;;; processing a value-slot binding AND the symbol is already lexically
234 ;;; bound or it is always lexical.
235
236 (define (bind-lexically? sym module)
237 (or (eq? module 'lexical)
238 (and (equal? module value-slot)
239 (let ((always (fluid-ref always-lexical)))
240 (or (eq? always 'all)
241 (memq sym always)
242 (get-lexical-binding (fluid-ref bindings-data) sym))))))
243
244 (define (split-let-bindings bindings module)
245 (let iterate ((tail bindings)
246 (lexical '())
247 (dynamic '()))
248 (if (null? tail)
249 (values (reverse lexical) (reverse dynamic))
250 (if (bind-lexically? (caar tail) module)
251 (iterate (cdr tail) (cons (car tail) lexical) dynamic)
252 (iterate (cdr tail) lexical (cons (car tail) dynamic))))))
253
254 ;;; Compile let and let* expressions. The code here is used both for
255 ;;; let/let* and flet/flet*, just with a different bindings module.
256 ;;;
257 ;;; A special module value 'lexical means that we're doing a lexical-let
258 ;;; instead and the bindings should not be saved to globals at all but
259 ;;; be done with the lexical framework instead.
260
261 ;;; Let is done with a single call to let-dynamic binding them locally
262 ;;; to new values all "at once". If there is at least one variable to
263 ;;; bind lexically among the bindings, we first do a let for all of them
264 ;;; to evaluate all values before any bindings take place, and then call
265 ;;; let-dynamic for the variables to bind dynamically.
266
267 (define (generate-let loc module bindings body)
268 (let ((bind (process-let-bindings loc bindings)))
269 (call-with-values
270 (lambda () (split-let-bindings bind module))
271 (lambda (lexical dynamic)
272 (for-each (lambda (sym)
273 (mark-global-needed! (fluid-ref bindings-data)
274 sym
275 module))
276 (map car dynamic))
277 (let ((make-values (lambda (for)
278 (map (lambda (el) (compile-expr (cdr el)))
279 for)))
280 (make-body (lambda ()
281 (make-sequence loc (map compile-expr body)))))
282 (if (null? lexical)
283 (let-dynamic loc (map car dynamic) module
284 (make-values dynamic) (make-body))
285 (let* ((lexical-syms (map (lambda (el) (gensym)) lexical))
286 (dynamic-syms (map (lambda (el) (gensym)) dynamic))
287 (all-syms (append lexical-syms dynamic-syms))
288 (vals (append (make-values lexical)
289 (make-values dynamic))))
290 (make-let loc
291 all-syms
292 all-syms
293 vals
294 (with-lexical-bindings
295 (fluid-ref bindings-data)
296 (map car lexical) lexical-syms
297 (lambda ()
298 (if (null? dynamic)
299 (make-body)
300 (let-dynamic loc
301 (map car dynamic)
302 module
303 (map
304 (lambda (sym)
305 (make-lexical-ref loc
306 sym
307 sym))
308 dynamic-syms)
309 (make-body)))))))))))))
310
311 ;;; Let* is compiled to a cascaded set of "small lets" for each binding
312 ;;; in turn so that each one already sees the preceding bindings.
313
314 (define (generate-let* loc module bindings body)
315 (let ((bind (process-let-bindings loc bindings)))
316 (begin
317 (for-each (lambda (sym)
318 (if (not (bind-lexically? sym module))
319 (mark-global-needed! (fluid-ref bindings-data)
320 sym
321 module)))
322 (map car bind))
323 (let iterate ((tail bind))
324 (if (null? tail)
325 (make-sequence loc (map compile-expr body))
326 (let ((sym (caar tail))
327 (value (compile-expr (cdar tail))))
328 (if (bind-lexically? sym module)
329 (let ((target (gensym)))
330 (make-let loc
331 `(,target)
332 `(,target)
333 `(,value)
334 (with-lexical-bindings
335 (fluid-ref bindings-data)
336 `(,sym)
337 `(,target)
338 (lambda () (iterate (cdr tail))))))
339 (let-dynamic loc
340 `(,(caar tail))
341 module
342 `(,value)
343 (iterate (cdr tail))))))))))
344
345 ;;; Split the argument list of a lambda expression into required,
346 ;;; optional and rest arguments and also check it is actually valid.
347 ;;; Additionally, we create a list of all "local variables" (that is,
348 ;;; required, optional and rest arguments together) and also this one
349 ;;; split into those to be bound lexically and dynamically. Returned is
350 ;;; as multiple values: required optional rest lexical dynamic
351
352 (define (bind-arg-lexical? arg)
353 (let ((always (fluid-ref always-lexical)))
354 (or (eq? always 'all)
355 (memq arg always))))
356
357 (define (split-lambda-arguments loc args)
358 (let iterate ((tail args)
359 (mode 'required)
360 (required '())
361 (optional '())
362 (lexical '())
363 (dynamic '()))
364 (cond
365 ((null? tail)
366 (let ((final-required (reverse required))
367 (final-optional (reverse optional))
368 (final-lexical (reverse lexical))
369 (final-dynamic (reverse dynamic)))
370 (values final-required
371 final-optional
372 #f
373 final-lexical
374 final-dynamic)))
375 ((and (eq? mode 'required)
376 (eq? (car tail) '&optional))
377 (iterate (cdr tail) 'optional required optional lexical dynamic))
378 ((eq? (car tail) '&rest)
379 (if (or (null? (cdr tail))
380 (not (null? (cddr tail))))
381 (report-error loc "expected exactly one symbol after &rest")
382 (let* ((rest (cadr tail))
383 (rest-lexical (bind-arg-lexical? rest))
384 (final-required (reverse required))
385 (final-optional (reverse optional))
386 (final-lexical (reverse (if rest-lexical
387 (cons rest lexical)
388 lexical)))
389 (final-dynamic (reverse (if rest-lexical
390 dynamic
391 (cons rest dynamic)))))
392 (values final-required
393 final-optional
394 rest
395 final-lexical
396 final-dynamic))))
397 (else
398 (if (not (symbol? (car tail)))
399 (report-error loc
400 "expected symbol in argument list, got"
401 (car tail))
402 (let* ((arg (car tail))
403 (bind-lexical (bind-arg-lexical? arg))
404 (new-lexical (if bind-lexical
405 (cons arg lexical)
406 lexical))
407 (new-dynamic (if bind-lexical
408 dynamic
409 (cons arg dynamic))))
410 (case mode
411 ((required) (iterate (cdr tail) mode
412 (cons arg required) optional
413 new-lexical new-dynamic))
414 ((optional) (iterate (cdr tail) mode
415 required (cons arg optional)
416 new-lexical new-dynamic))
417 (else
418 (error "invalid mode in split-lambda-arguments"
419 mode)))))))))
420
421 ;;; Compile a lambda expression. One thing we have to be aware of is
422 ;;; that lambda arguments are usually dynamically bound, even when a
423 ;;; lexical binding is intact for a symbol. For symbols that are marked
424 ;;; as 'always lexical,' however, we lexically bind here as well, and
425 ;;; thus we get them out of the let-dynamic call and register a lexical
426 ;;; binding for them (the lexical target variable is already there,
427 ;;; namely the real lambda argument from TreeIL).
428
429 (define (compile-lambda loc args body)
430 (if (not (list? args))
431 (report-error loc "expected list for argument-list" args))
432 (if (null? body)
433 (report-error loc "function body must not be empty"))
434 (receive (required optional rest lexical dynamic)
435 (split-lambda-arguments loc args)
436 (define (process-args args)
437 (define (find-pairs pairs filter)
438 (lset-intersection (lambda (name+sym x)
439 (eq? (car name+sym) x))
440 pairs
441 filter))
442 (let* ((syms (map (lambda (x) (gensym)) args))
443 (pairs (map cons args syms))
444 (lexical-pairs (find-pairs pairs lexical))
445 (dynamic-pairs (find-pairs pairs dynamic)))
446 (values syms pairs lexical-pairs dynamic-pairs)))
447 (let*-values (((required-syms
448 required-pairs
449 required-lex-pairs
450 required-dyn-pairs)
451 (process-args required))
452 ((optional-syms
453 optional-pairs
454 optional-lex-pairs
455 optional-dyn-pairs)
456 (process-args optional))
457 ((rest-syms rest-pairs rest-lex-pairs rest-dyn-pairs)
458 (process-args (if rest (list rest) '())))
459 ((the-rest-sym) (if rest (car rest-syms) #f))
460 ((all-syms) (append required-syms
461 optional-syms
462 rest-syms))
463 ((all-lex-pairs) (append required-lex-pairs
464 optional-lex-pairs
465 rest-lex-pairs))
466 ((all-dyn-pairs) (append required-dyn-pairs
467 optional-dyn-pairs
468 rest-dyn-pairs)))
469 (for-each (lambda (sym)
470 (mark-global-needed! (fluid-ref bindings-data)
471 sym
472 value-slot))
473 dynamic)
474 (with-dynamic-bindings
475 (fluid-ref bindings-data)
476 dynamic
477 (lambda ()
478 (with-lexical-bindings
479 (fluid-ref bindings-data)
480 (map car all-lex-pairs)
481 (map cdr all-lex-pairs)
482 (lambda ()
483 (make-lambda
484 loc
485 '()
486 (make-lambda-case
487 #f
488 required
489 optional
490 rest
491 #f
492 (map (lambda (x) (nil-value loc)) optional)
493 all-syms
494 (let ((compiled-body
495 (make-sequence loc (map compile-expr body))))
496 (make-sequence
497 loc
498 (list
499 (if rest
500 (make-conditional
501 loc
502 (call-primitive loc
503 'null?
504 (make-lexical-ref loc
505 rest
506 the-rest-sym))
507 (make-lexical-set loc
508 rest
509 the-rest-sym
510 (nil-value loc))
511 (make-void loc))
512 (make-void loc))
513 (if (null? dynamic)
514 compiled-body
515 (let-dynamic loc
516 dynamic
517 value-slot
518 (map (lambda (name-sym)
519 (make-lexical-ref
520 loc
521 (car name-sym)
522 (cdr name-sym)))
523 all-dyn-pairs)
524 compiled-body)))))
525 #f)))))))))
526
527 ;;; Handle the common part of defconst and defvar, that is, checking for
528 ;;; a correct doc string and arguments as well as maybe in the future
529 ;;; handling the docstring somehow.
530
531 (define (handle-var-def loc sym doc)
532 (cond
533 ((not (symbol? sym)) (report-error loc "expected symbol, got" sym))
534 ((> (length doc) 1) (report-error loc "too many arguments to defvar"))
535 ((and (not (null? doc)) (not (string? (car doc))))
536 (report-error loc "expected string as third argument of defvar, got"
537 (car doc)))
538 ;; TODO: Handle doc string if present.
539 (else #t)))
540
541 ;;; Handle macro bindings.
542
543 (define (is-macro? sym)
544 (and
545 (symbol? sym)
546 (module-defined? (resolve-interface function-slot) sym)
547 (let ((macro (module-ref (resolve-module function-slot) sym)))
548 (and (pair? macro) (eq? (car macro) 'macro)))))
549
550 (define (define-macro! loc sym definition)
551 (let ((resolved (resolve-module function-slot)))
552 (module-define! resolved sym (cons 'macro definition))
553 (module-export! resolved (list sym))))
554
555 (define (get-macro sym)
556 (and
557 (is-macro? sym)
558 (cdr (module-ref (resolve-module function-slot) sym))))
559
560 ;;; See if a (backquoted) expression contains any unquotes.
561
562 (define (contains-unquotes? expr)
563 (if (pair? expr)
564 (if (or (unquote? (car expr)) (unquote-splicing? (car expr)))
565 #t
566 (or (contains-unquotes? (car expr))
567 (contains-unquotes? (cdr expr))))
568 #f))
569
570 ;;; Process a backquoted expression by building up the needed
571 ;;; cons/append calls. For splicing, it is assumed that the expression
572 ;;; spliced in evaluates to a list. The emacs manual does not really
573 ;;; state either it has to or what to do if it does not, but Scheme
574 ;;; explicitly forbids it and this seems reasonable also for elisp.
575
576 (define (unquote-cell? expr)
577 (and (list? expr) (= (length expr) 2) (unquote? (car expr))))
578
579 (define (unquote-splicing-cell? expr)
580 (and (list? expr) (= (length expr) 2) (unquote-splicing? (car expr))))
581
582 (define (process-backquote loc expr)
583 (if (contains-unquotes? expr)
584 (if (pair? expr)
585 (if (or (unquote-cell? expr) (unquote-splicing-cell? expr))
586 (compile-expr (cadr expr))
587 (let* ((head (car expr))
588 (processed-tail (process-backquote loc (cdr expr)))
589 (head-is-list-2 (and (list? head)
590 (= (length head) 2)))
591 (head-unquote (and head-is-list-2
592 (unquote? (car head))))
593 (head-unquote-splicing (and head-is-list-2
594 (unquote-splicing?
595 (car head)))))
596 (if head-unquote-splicing
597 (call-primitive loc
598 'append
599 (compile-expr (cadr head))
600 processed-tail)
601 (call-primitive loc 'cons
602 (if head-unquote
603 (compile-expr (cadr head))
604 (process-backquote loc head))
605 processed-tail))))
606 (report-error loc
607 "non-pair expression contains unquotes"
608 expr))
609 (make-const loc expr)))
610
611 ;;; Temporarily update a list of symbols that are handled specially
612 ;;; (disabled void check or always lexical) for compiling body. We need
613 ;;; to handle special cases for already all / set to all and the like.
614
615 (define (with-added-symbols loc fluid syms body)
616 (if (null? body)
617 (report-error loc "symbol-list construct has empty body"))
618 (if (not (or (eq? syms 'all)
619 (and (list? syms) (and-map symbol? syms))))
620 (report-error loc "invalid symbol list" syms))
621 (let ((old (fluid-ref fluid))
622 (make-body (lambda ()
623 (make-sequence loc (map compile-expr body)))))
624 (if (eq? old 'all)
625 (make-body)
626 (let ((new (if (eq? syms 'all)
627 'all
628 (append syms old))))
629 (with-fluids ((fluid new))
630 (make-body))))))
631
632 ;;; Compile a symbol expression. This is a variable reference or maybe
633 ;;; some special value like nil.
634
635 (define (compile-symbol loc sym)
636 (case sym
637 ((nil) (nil-value loc))
638 ((t) (t-value loc))
639 (else (reference-with-check loc sym value-slot))))
640
641 ;;; Compile a pair-expression (that is, any structure-like construct).
642
643 (define (compile-pair loc expr)
644 (pmatch expr
645 ((progn . ,forms)
646 (make-sequence loc (map compile-expr forms)))
647
648 ((if ,condition ,ifclause)
649 (make-conditional loc
650 (compile-expr condition)
651 (compile-expr ifclause)
652 (nil-value loc)))
653
654 ((if ,condition ,ifclause ,elseclause)
655 (make-conditional loc
656 (compile-expr condition)
657 (compile-expr ifclause)
658 (compile-expr elseclause)))
659
660 ((if ,condition ,ifclause . ,elses)
661 (make-conditional loc
662 (compile-expr condition)
663 (compile-expr ifclause)
664 (make-sequence loc (map compile-expr elses))))
665
666 ;; defconst and defvar are kept here in the compiler (rather than
667 ;; doing them as macros) for if we may want to handle the docstring
668 ;; somehow.
669
670 ((defconst ,sym ,value . ,doc)
671 (if (handle-var-def loc sym doc)
672 (make-sequence loc
673 (list (set-variable! loc
674 sym
675 value-slot
676 (compile-expr value))
677 (make-const loc sym)))))
678
679 ((defvar ,sym) (make-const loc sym))
680
681 ((defvar ,sym ,value . ,doc)
682 (if (handle-var-def loc sym doc)
683 (make-sequence
684 loc
685 (list (make-conditional
686 loc
687 (call-primitive loc
688 'eq?
689 (make-module-ref loc runtime 'void #t)
690 (reference-variable loc sym value-slot))
691 (set-variable! loc sym value-slot (compile-expr value))
692 (make-void loc))
693 (make-const loc sym)))))
694
695 ;; Build a set form for possibly multiple values. The code is not
696 ;; formulated tail recursive because it is clearer this way and
697 ;; large lists of symbol expression pairs are very unlikely.
698
699 ((setq . ,args) (guard (not (null? args)))
700 (make-sequence
701 loc
702 (let iterate ((tail args))
703 (let ((sym (car tail))
704 (tailtail (cdr tail)))
705 (if (not (symbol? sym))
706 (report-error loc "expected symbol in setq")
707 (if (null? tailtail)
708 (report-error loc
709 "missing value for symbol in setq"
710 sym)
711 (let* ((val (compile-expr (car tailtail)))
712 (op (set-variable! loc sym value-slot val)))
713 (if (null? (cdr tailtail))
714 (let* ((temp (gensym))
715 (ref (make-lexical-ref loc temp temp)))
716 (list (make-let
717 loc
718 `(,temp)
719 `(,temp)
720 `(,val)
721 (make-sequence
722 loc
723 (list (set-variable! loc
724 sym
725 value-slot
726 ref)
727 ref)))))
728 (cons (set-variable! loc sym value-slot val)
729 (iterate (cdr tailtail)))))))))))
730
731 ;; All lets (let, flet, lexical-let and let* forms) are done using
732 ;; the generate-let/generate-let* methods.
733
734 ((let ,bindings . ,body) (guard (and (list? bindings)
735 (not (null? bindings))
736 (not (null? body))))
737 (generate-let loc value-slot bindings body))
738
739 ((lexical-let ,bindings . ,body) (guard (and (list? bindings)
740 (not (null? bindings))
741 (not (null? body))))
742 (generate-let loc 'lexical bindings body))
743
744 ((flet ,bindings . ,body) (guard (and (list? bindings)
745 (not (null? bindings))
746 (not (null? body))))
747 (generate-let loc function-slot bindings body))
748
749 ((let* ,bindings . ,body) (guard (and (list? bindings)
750 (not (null? bindings))
751 (not (null? body))))
752 (generate-let* loc value-slot bindings body))
753
754 ((lexical-let* ,bindings . ,body) (guard (and (list? bindings)
755 (not (null? bindings))
756 (not (null? body))))
757 (generate-let* loc 'lexical bindings body))
758
759 ((flet* ,bindings . ,body) (guard (and (list? bindings)
760 (not (null? bindings))
761 (not (null? body))))
762 (generate-let* loc function-slot bindings body))
763
764 ;; Temporarily disable void checks or set symbols as always lexical
765 ;; only for the lexical scope of a construct.
766
767 ((without-void-checks ,syms . ,body)
768 (with-added-symbols loc disable-void-check syms body))
769
770 ((with-always-lexical ,syms . ,body)
771 (with-added-symbols loc always-lexical syms body))
772
773 ;; guile-ref allows building TreeIL's module references from within
774 ;; elisp as a way to access data within the Guile universe. The
775 ;; module and symbol referenced are static values, just like (@
776 ;; module symbol) does!
777
778 ((guile-ref ,module ,sym) (guard (and (list? module) (symbol? sym)))
779 (make-module-ref loc module sym #t))
780
781 ;; guile-primitive allows to create primitive references, which are
782 ;; still a little faster.
783
784 ((guile-primitive ,sym) (guard (symbol? sym))
785 (make-primitive-ref loc sym))
786
787 ;; A while construct is transformed into a tail-recursive loop like
788 ;; this:
789 ;;
790 ;; (letrec ((iterate (lambda ()
791 ;; (if condition
792 ;; (begin body
793 ;; (iterate))
794 ;; #nil))))
795 ;; (iterate))
796 ;;
797 ;; As letrec is not directly accessible from elisp, while is
798 ;; implemented here instead of with a macro.
799
800 ((while ,condition . ,body)
801 (let* ((itersym (gensym))
802 (compiled-body (map compile-expr body))
803 (iter-call (make-application loc
804 (make-lexical-ref loc
805 'iterate
806 itersym)
807 (list)))
808 (full-body (make-sequence loc
809 `(,@compiled-body ,iter-call)))
810 (lambda-body (make-conditional loc
811 (compile-expr condition)
812 full-body
813 (nil-value loc)))
814 (iter-thunk (make-lambda loc
815 '()
816 (make-lambda-case #f
817 '()
818 #f
819 #f
820 #f
821 '()
822 '()
823 lambda-body
824 #f))))
825 (make-letrec loc
826 #f
827 '(iterate)
828 (list itersym)
829 (list iter-thunk)
830 iter-call)))
831
832 ;; Either (lambda ...) or (function (lambda ...)) denotes a
833 ;; lambda-expression that should be compiled.
834
835 ((lambda ,args . ,body)
836 (compile-lambda loc args body))
837
838 ((function (lambda ,args . ,body))
839 (compile-lambda loc args body))
840
841 ;; Build a lambda and also assign it to the function cell of some
842 ;; symbol. This is no macro as we might want to honour the docstring
843 ;; at some time; just as with defvar/defconst.
844
845 ((defun ,name ,args . ,body)
846 (if (not (symbol? name))
847 (report-error loc "expected symbol as function name" name)
848 (make-sequence loc
849 (list (set-variable! loc
850 name
851 function-slot
852 (compile-lambda loc
853 args
854 body))
855 (make-const loc name)))))
856
857 ;; Define a macro (this is done directly at compile-time!). FIXME:
858 ;; Recursive macros don't work!
859
860 ((defmacro ,name ,args . ,body)
861 (if (not (symbol? name))
862 (report-error loc "expected symbol as macro name" name)
863 (let* ((tree-il (compile-lambda loc args body))
864 (object (compile tree-il #:from 'tree-il #:to 'value)))
865 (define-macro! loc name object)
866 (make-const loc name))))
867
868 ;; XXX: Maybe we could implement backquotes in macros, too.
869
870 ((,backq ,val) (guard (backquote? backq))
871 (process-backquote loc val))
872
873 ;; XXX: Why do we need 'quote here instead of quote?
874
875 (('quote ,val)
876 (make-const loc val))
877
878 ;; Macro calls are simply expanded and recursively compiled.
879
880 ((,macro . ,args) (guard (is-macro? macro))
881 (compile-expr (apply (get-macro macro) args)))
882
883 ;; Function calls using (function args) standard notation; here, we
884 ;; have to take the function value of a symbol if it is one. It
885 ;; seems that functions in form of uncompiled lists are not
886 ;; supported in this syntax, so we don't have to care for them.
887
888 ((,func . ,args)
889 (make-application loc
890 (if (symbol? func)
891 (reference-with-check loc func function-slot)
892 (compile-expr func))
893 (map compile-expr args)))
894
895 (else
896 (report-error loc "unrecognized elisp" expr))))
897
898 ;;; Compile a single expression to TreeIL.
899
900 (define (compile-expr expr)
901 (let ((loc (location expr)))
902 (cond
903 ((symbol? expr)
904 (compile-symbol loc expr))
905 ((pair? expr)
906 (compile-pair loc expr))
907 (else (make-const loc expr)))))
908
909 ;;; Process the compiler options.
910 ;;; FIXME: Why is '(()) passed as options by the REPL?
911
912 (define (valid-symbol-list-arg? value)
913 (or (eq? value 'all)
914 (and (list? value) (and-map symbol? value))))
915
916 (define (process-options! opt)
917 (if (and (not (null? opt))
918 (not (equal? opt '(()))))
919 (if (null? (cdr opt))
920 (report-error #f "Invalid compiler options" opt)
921 (let ((key (car opt))
922 (value (cadr opt)))
923 (case key
924 ((#:disable-void-check)
925 (if (valid-symbol-list-arg? value)
926 (fluid-set! disable-void-check value)
927 (report-error #f
928 "Invalid value for #:disable-void-check"
929 value)))
930 ((#:always-lexical)
931 (if (valid-symbol-list-arg? value)
932 (fluid-set! always-lexical value)
933 (report-error #f
934 "Invalid value for #:always-lexical"
935 value)))
936 (else (report-error #f
937 "Invalid compiler option"
938 key)))))))
939
940 ;;; Entry point for compilation to TreeIL. This creates the bindings
941 ;;; data structure, and after compiling the main expression we need to
942 ;;; make sure all globals for symbols used during the compilation are
943 ;;; created using the generate-ensure-global function.
944
945 (define (compile-tree-il expr env opts)
946 (values
947 (with-fluids ((bindings-data (make-bindings))
948 (disable-void-check '())
949 (always-lexical '()))
950 (process-options! opts)
951 (let ((loc (location expr))
952 (compiled (compile-expr expr)))
953 (make-sequence loc
954 `(,@(map-globals-needed
955 (fluid-ref bindings-data)
956 (lambda (mod sym)
957 (generate-ensure-global loc sym mod)))
958 ,compiled))))
959 env
960 env))