3550b5b414fdf12e70e2a461fd9d724739db31b1
[bpt/guile.git] / module / language / elisp / boot.el
1 ;;; Guile Emacs Lisp -*- lexical-binding: t -*-
2
3 ;;; Copyright (C) 2011 Free Software Foundation, Inc.
4
5 ;;; This library is free software; you can redistribute it and/or modify
6 ;;; it under the terms of the GNU Lesser General Public License as
7 ;;; published by the Free Software Foundation; either version 3 of the
8 ;;; License, or (at your option) any later version.
9 ;;;
10 ;;; This library is distributed in the hope that it will be useful, but
11 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
12 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ;;; Lesser General Public License for more details.
14 ;;;
15 ;;; You should have received a copy of the GNU Lesser General Public
16 ;;; License along with this library; if not, write to the Free Software
17 ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 ;;; 02110-1301 USA
19
20 ;;; Code:
21
22 (defmacro @ (module symbol)
23 `(guile-ref ,module ,symbol))
24
25 (defmacro defun (name args &rest body)
26 `(let ((proc (function (lambda ,args ,@body))))
27 (%funcall (@ (language elisp runtime) set-symbol-function!)
28 ',name
29 proc)
30 (%funcall (@ (guile) set-procedure-property!)
31 proc 'name ',name)
32 ',name))
33
34 (defun omega () (omega))
35
36 (defmacro eval-and-compile (&rest body)
37 `(progn
38 (eval-when-compile ,@body)
39 (progn ,@body)))
40
41 (eval-and-compile
42 (defun eval (form)
43 (%funcall (@ (language elisp runtime) eval-elisp) form)))
44
45 (eval-and-compile
46 (defun null (object)
47 (if object nil t))
48 (defun consp (object)
49 (%funcall (@ (guile) pair?) object))
50 (defun listp (object)
51 (if object (consp object) t))
52 (defun car (list)
53 (if list (%funcall (@ (guile) car) list) nil))
54 (defun cdr (list)
55 (if list (%funcall (@ (guile) cdr) list) nil))
56 (defun make-symbol (name)
57 (%funcall (@ (guile) make-symbol) name))
58 (defun gensym ()
59 (%funcall (@ (guile) gensym)))
60 (defun signal (error-symbol data)
61 (%funcall (@ (guile) throw) 'elisp-condition error-symbol data)))
62
63 (defmacro lambda (&rest cdr)
64 `#'(lambda ,@cdr))
65
66 (defmacro prog1 (first &rest body)
67 (let ((temp (gensym)))
68 `(let ((,temp ,first))
69 (declare (lexical ,temp))
70 ,@body
71 ,temp)))
72
73 (defun interactive (&optional arg)
74 nil)
75
76 (defmacro prog2 (form1 form2 &rest body)
77 `(progn ,form1 (prog1 ,form2 ,@body)))
78
79 (defmacro cond (&rest clauses)
80 (if (null clauses)
81 nil
82 (let ((first (car clauses))
83 (rest (cdr clauses)))
84 (if (listp first)
85 (let ((condition (car first))
86 (body (cdr first)))
87 (if (null body)
88 (let ((temp (gensym)))
89 `(let ((,temp ,condition))
90 (declare (lexical ,temp))
91 (if ,temp
92 ,temp
93 (cond ,@rest))))
94 `(if ,condition
95 (progn ,@body)
96 (cond ,@rest))))
97 (signal 'wrong-type-argument `(listp ,first))))))
98
99 (defmacro and (&rest conditions)
100 (cond ((null conditions) t)
101 ((null (cdr conditions)) (car conditions))
102 (t `(if ,(car conditions)
103 (and ,@(cdr conditions))
104 nil))))
105
106 (defmacro or (&rest conditions)
107 (cond ((null conditions) nil)
108 ((null (cdr conditions)) (car conditions))
109 (t (let ((temp (gensym)))
110 `(let ((,temp ,(car conditions)))
111 (declare (lexical ,temp))
112 (if ,temp
113 ,temp
114 (or ,@(cdr conditions))))))))
115
116 (defmacro lexical-let (bindings &rest body)
117 (labels ((loop (list vars)
118 (if (null list)
119 `(let ,bindings
120 (declare (lexical ,@vars))
121 ,@body)
122 (loop (cdr list)
123 (if (consp (car list))
124 `(,(car (car list)) ,@vars)
125 `(,(car list) ,@vars))))))
126 (loop bindings '())))
127
128 (defmacro lexical-let* (bindings &rest body)
129 (labels ((loop (list vars)
130 (if (null list)
131 `(let* ,bindings
132 (declare (lexical ,@vars))
133 ,@body)
134 (loop (cdr list)
135 (if (consp (car list))
136 (cons (car (car list)) vars)
137 (cons (car list) vars))))))
138 (loop bindings '())))
139
140 (defmacro while (test &rest body)
141 (let ((loop (gensym)))
142 `(labels ((,loop ()
143 (if ,test
144 (progn ,@body (,loop))
145 nil)))
146 (,loop))))
147
148 (defmacro unwind-protect (bodyform &rest unwindforms)
149 `(%funcall (@ (guile) dynamic-wind)
150 #'(lambda () nil)
151 #'(lambda () ,bodyform)
152 #'(lambda () ,@unwindforms)))
153
154 (defmacro when (cond &rest body)
155 `(if ,cond
156 (progn ,@body)))
157
158 (defmacro unless (cond &rest body)
159 `(when (not ,cond)
160 ,@body))
161
162 (defun symbolp (object)
163 (%funcall (@ (guile) symbol?) object))
164
165 (defun %functionp (object)
166 (%funcall (@ (guile) procedure?) object))
167
168 (defun symbol-function (symbol)
169 (let ((f (%funcall (@ (language elisp runtime) symbol-function)
170 symbol)))
171 (if (%funcall (@ (language elisp falias) falias?) f)
172 (%funcall (@ (language elisp falias) falias-object) f)
173 f)))
174
175 (defun eval (form)
176 (%funcall (@ (system base compile) compile)
177 form
178 (%funcall (@ (guile) symbol->keyword) 'from)
179 'elisp
180 (%funcall (@ (guile) symbol->keyword) 'to)
181 'value))
182
183 (defun %indirect-function (object)
184 (cond
185 ((%functionp object)
186 object)
187 ((null object)
188 (signal 'void-function nil))
189 ((symbolp object) ;++ cycle detection
190 (%indirect-function
191 (%funcall (@ (language elisp runtime) symbol-function) object)))
192 ((listp object)
193 (eval `(function ,object)))
194 (t
195 (signal 'invalid-function `(,object)))))
196
197 (defun apply (function &rest arguments)
198 (%funcall (@ (guile) apply)
199 (@ (guile) apply)
200 (%indirect-function function)
201 arguments))
202
203 (defun funcall (function &rest arguments)
204 (%funcall (@ (guile) apply)
205 (%indirect-function function)
206 arguments))
207
208 (defun autoload-do-load (fundef &optional funname macro-only)
209 (and (load (cadr fundef))
210 (%indirect-function funname)))
211
212 (defun fset (symbol definition)
213 (funcall (@ (language elisp runtime) set-symbol-function!)
214 symbol
215 definition))
216
217 (defun eq (obj1 obj2)
218 (if obj1
219 (%funcall (@ (guile) eq?) obj1 obj2)
220 (if obj2 nil t)))
221
222 (defun nthcdr (n list)
223 (let ((i 0))
224 (while (< i n)
225 (setq list (cdr list)
226 i (+ i 1)))
227 list))
228
229 (defun nth (n list)
230 (car (nthcdr n list)))
231
232 (defun fset (symbol definition)
233 (funcall (@ (language elisp runtime) set-symbol-function!)
234 symbol
235 (cond
236 ((%funcall (@ (guile) procedure?) definition)
237 definition)
238 ((and (consp definition)
239 (eq (car definition) 'macro))
240 (if (%funcall (@ (guile) procedure?) (cdr definition))
241 definition
242 (cons 'macro
243 (funcall (@ (language elisp falias) make-falias)
244 (function
245 (lambda (&rest args) (apply (cdr definition) args)))
246 (cdr definition)))))
247 ((and (consp definition)
248 (eq (car definition) 'autoload))
249 (if (or (eq (nth 4 definition) 'macro)
250 (eq (nth 4 definition) t))
251 (cons 'macro
252 (funcall
253 (@ (language elisp falias) make-falias)
254 (function (lambda (&rest args)
255 (apply (cdr (autoload-do-load definition symbol nil)) args)))
256 definition))
257 (funcall
258 (@ (language elisp falias) make-falias)
259 (function (lambda (&rest args)
260 (apply (autoload-do-load definition symbol nil) args)))
261 definition)))
262 (t
263 (funcall (@ (language elisp falias) make-falias)
264 (function (lambda (&rest args) (apply definition args)))
265 definition))))
266 definition)
267
268 (defun gload (file)
269 (funcall (@ (system base compile) compile-file)
270 file
271 (funcall (@ (guile) symbol->keyword) 'from)
272 'elisp
273 (funcall (@ (guile) symbol->keyword) 'to)
274 'value)
275 t)
276
277 ;;; Equality predicates
278
279 (defun eql (obj1 obj2)
280 (if obj1
281 (funcall (@ (guile) eqv?) obj1 obj2)
282 (null obj2)))
283
284 (defun equal (obj1 obj2)
285 (if obj1
286 (funcall (@ (guile) equal?) obj1 obj2)
287 (null obj2)))
288
289 ;;; Symbols
290
291 ;;; `symbolp' and `symbol-function' are defined above.
292
293 (fset 'symbol-name (@ (guile) symbol->string))
294 (fset 'symbol-value (@ (language elisp runtime) symbol-value))
295 (fset 'set (@ (language elisp runtime) set-symbol-value!))
296 (fset 'makunbound (@ (language elisp runtime) makunbound!))
297 (fset 'fmakunbound (@ (language elisp runtime) fmakunbound!))
298 (fset 'boundp (@ (language elisp runtime) symbol-bound?))
299 (fset 'fboundp (@ (language elisp runtime) symbol-fbound?))
300 (fset 'intern (@ (guile) string->symbol))
301
302 ;(defun defvaralias (new-alias base-variable &optional docstring)
303 ; (let ((fluid (funcall (@ (language elisp runtime) symbol-fluid)
304 ; base-variable)))
305 ; (funcall (@ (language elisp runtime) set-symbol-fluid!)
306 ; new-alias
307 ; fluid)
308 ; base-variable))
309
310 ;;; Numerical type predicates
311
312 (defun floatp (object)
313 (and (funcall (@ (guile) real?) object)
314 (or (funcall (@ (guile) inexact?) object)
315 (null (funcall (@ (guile) integer?) object)))))
316
317 (defun integerp (object)
318 (and (funcall (@ (guile) integer?) object)
319 (funcall (@ (guile) exact?) object)))
320
321 (defun numberp (object)
322 (funcall (@ (guile) real?) object))
323
324 (defun wholenump (object)
325 (and (integerp object) (>= object 0)))
326
327 (defun zerop (object)
328 (= object 0))
329
330 ;;; Numerical comparisons
331
332 (fset '= (@ (guile) =))
333
334 (defun /= (num1 num2)
335 (null (= num1 num2)))
336
337 (fset '< (@ (guile) <))
338 (fset '<= (@ (guile) <=))
339 (fset '> (@ (guile) >))
340 (fset '>= (@ (guile) >=))
341
342 (defun max (&rest numbers)
343 (apply (@ (guile) max) numbers))
344
345 (defun min (&rest numbers)
346 (apply (@ (guile) min) numbers))
347
348 ;;; Arithmetic functions
349
350 (fset '1+ (@ (guile) 1+))
351 (fset '1- (@ (guile) 1-))
352 (fset '+ (@ (guile) +))
353 (fset '- (@ (guile) -))
354 (fset '* (@ (guile) *))
355 (fset '% (@ (guile) modulo))
356 (fset 'abs (@ (guile) abs))
357
358 ;;; Floating-point rounding
359
360 (fset 'ffloor (@ (guile) floor))
361 (fset 'fceiling (@ (guile) ceiling))
362 (fset 'ftruncate (@ (guile) truncate))
363 (fset 'fround (@ (guile) round))
364
365 ;;; Numeric conversion
366
367 (defun float (arg)
368 (if (numberp arg)
369 (funcall (@ (guile) exact->inexact) arg)
370 (signal 'wrong-type-argument `(numberp ,arg))))
371
372 ;;; List predicates
373
374 (fset 'not #'null)
375
376 (defun atom (object)
377 (null (consp object)))
378
379 (defun nlistp (object)
380 (null (listp object)))
381
382 ;;; Lists
383
384 (fset 'cons (@ (guile) cons))
385 (fset 'list (@ (guile) list))
386 (fset 'make-list (@ (guile) make-list))
387 (fset 'append (@ (guile) append))
388 (fset 'reverse (@ (guile) reverse))
389 (fset 'nreverse (@ (guile) reverse!))
390
391 (defun car-safe (object)
392 (if (consp object)
393 (car object)
394 nil))
395
396 (defun cdr-safe (object)
397 (if (consp object)
398 (cdr object)
399 nil))
400
401 (defun setcar (cell newcar)
402 (if (consp cell)
403 (progn
404 (funcall (@ (guile) set-car!) cell newcar)
405 newcar)
406 (signal 'wrong-type-argument `(consp ,cell))))
407
408 (defun setcdr (cell newcdr)
409 (if (consp cell)
410 (progn
411 (funcall (@ (guile) set-cdr!) cell newcdr)
412 newcdr)
413 (signal 'wrong-type-argument `(consp ,cell))))
414
415 (defun %member (elt list test)
416 (cond
417 ((null list) nil)
418 ((consp list)
419 (if (funcall test elt (car list))
420 list
421 (%member elt (cdr list) test)))
422 (t (signal 'wrong-type-argument `(listp ,list)))))
423
424 (defun member (elt list)
425 (%member elt list #'equal))
426
427 (defun memql (elt list)
428 (%member elt list #'eql))
429
430 (defun memq (elt list)
431 (%member elt list #'eq))
432
433 (defun assoc (key list)
434 (funcall (@ (srfi srfi-1) assoc) key list #'equal))
435
436 (defun assq (key list)
437 (funcall (@ (srfi srfi-1) assoc) key list #'eq))
438
439 (defun rplaca (cell newcar)
440 (funcall (@ (guile) set-car!) cell newcar)
441 newcar)
442
443 (defun rplacd (cell newcdr)
444 (funcall (@ (guile) set-cdr!) cell newcdr)
445 newcdr)
446
447 (defun caar (x)
448 (car (car x)))
449
450 (defun cadr (x)
451 (car (cdr x)))
452
453 (defun cdar (x)
454 (cdr (car x)))
455
456 (defun cddr (x)
457 (cdr (cdr x)))
458
459 (defmacro dolist (spec &rest body)
460 (apply #'(lambda (var list &optional result)
461 (list 'progn
462 (list 'mapc
463 (cons 'lambda (cons (list var) body))
464 list)
465 result))
466 spec))
467
468 ;;; Strings
469
470 (defun string (&rest characters)
471 (funcall (@ (guile) list->string)
472 (mapcar (@ (guile) integer->char) characters)))
473
474 (defun stringp (object)
475 (funcall (@ (guile) string?) object))
476
477 (defun string-equal (s1 s2)
478 (let ((s1 (if (symbolp s1) (symbol-name s1) s1))
479 (s2 (if (symbolp s2) (symbol-name s2) s2)))
480 (funcall (@ (guile) string=?) s1 s2)))
481
482 (fset 'string= 'string-equal)
483
484 (defun substring (string from &optional to)
485 (apply (@ (guile) substring) string from (if to (list to) nil)))
486
487 (defun upcase (obj)
488 (funcall (@ (guile) string-upcase) obj))
489
490 (defun downcase (obj)
491 (funcall (@ (guile) string-downcase) obj))
492
493 (defun string-match (regexp string &optional start)
494 (let ((m (funcall (@ (ice-9 regex) string-match)
495 regexp
496 string
497 (or start 0))))
498 (if m
499 (funcall (@ (ice-9 regex) match:start) m 0)
500 nil)))
501
502 ;; Vectors
503
504 (defun make-vector (length init)
505 (funcall (@ (guile) make-vector) length init))
506
507 ;;; Sequences
508
509 (defun length (sequence)
510 (funcall (if (listp sequence)
511 (@ (guile) length)
512 (@ (guile) generalized-vector-length))
513 sequence))
514
515 (defun mapcar (function sequence)
516 (funcall (@ (guile) map) function sequence))
517
518 (defun mapc (function sequence)
519 (funcall (@ (guile) for-each) function sequence)
520 sequence)
521
522 (defun aref (array idx)
523 (funcall (@ (guile) generalized-vector-ref) array idx))
524
525 (defun aset (array idx newelt)
526 (funcall (@ (guile) generalized-vector-set!) array idx newelt)
527 newelt)
528
529 (defun concat (&rest sequences)
530 (apply (@ (guile) string-append) sequences))
531
532 ;;; Property lists
533
534 (defun %plist-member (plist property test)
535 (cond
536 ((null plist) nil)
537 ((consp plist)
538 (if (funcall test (car plist) property)
539 (cdr plist)
540 (%plist-member (cdr (cdr plist)) property test)))
541 (t (signal 'wrong-type-argument `(listp ,plist)))))
542
543 (defun %plist-get (plist property test)
544 (car (%plist-member plist property test)))
545
546 (defun %plist-put (plist property value test)
547 (let ((x (%plist-member plist property test)))
548 (if x
549 (progn (setcar x value) plist)
550 (cons property (cons value plist)))))
551
552 (defun plist-get (plist property)
553 (%plist-get plist property #'eq))
554
555 (defun plist-put (plist property value)
556 (%plist-put plist property value #'eq))
557
558 (defun plist-member (plist property)
559 (%plist-member plist property #'eq))
560
561 (defun lax-plist-get (plist property)
562 (%plist-get plist property #'equal))
563
564 (defun lax-plist-put (plist property value)
565 (%plist-put plist property value #'equal))
566
567 (defvar plist-function (funcall (@ (guile) make-object-property)))
568
569 (defun symbol-plist (symbol)
570 (funcall plist-function symbol))
571
572 (defun setplist (symbol plist)
573 (funcall (funcall (@ (guile) setter) plist-function) symbol plist))
574
575 (defun get (symbol propname)
576 (plist-get (symbol-plist symbol) propname))
577
578 (defun put (symbol propname value)
579 (setplist symbol (plist-put (symbol-plist symbol) propname value)))
580
581 ;;; Nonlocal exits
582
583 (defmacro condition-case (var bodyform &rest handlers)
584 (let ((key (make-symbol "key"))
585 (error-symbol (make-symbol "error-symbol"))
586 (data (make-symbol "data"))
587 (conditions (make-symbol "conditions")))
588 (flet ((handler->cond-clause (handler)
589 `((or ,@(mapcar #'(lambda (c) `(memq ',c ,conditions))
590 (if (consp (car handler))
591 (car handler)
592 (list (car handler)))))
593 ,@(cdr handler))))
594 `(funcall (@ (guile) catch)
595 'elisp-condition
596 #'(lambda () ,bodyform)
597 #'(lambda (,key ,error-symbol ,data)
598 (declare (lexical ,key ,error-symbol ,data))
599 (let ((,conditions
600 (get ,error-symbol 'error-conditions))
601 ,@(if var
602 `((,var (cons ,error-symbol ,data)))
603 '()))
604 (declare (lexical ,conditions
605 ,@(if var `(,var) '())))
606 (cond ,@(mapcar #'handler->cond-clause handlers)
607 (t (signal ,error-symbol ,data)))))))))
608
609 (put 'error 'error-conditions '(error))
610 (put 'wrong-type-argument 'error-conditions '(wrong-type-argument error))
611 (put 'invalid-function 'error-conditions '(invalid-function error))
612 (put 'no-catch 'error-conditions '(no-catch error))
613 (put 'throw 'error-conditions '(throw))
614
615 (defvar %catch nil)
616
617 (defmacro catch (tag &rest body)
618 (let ((tag-value (make-symbol "tag-value"))
619 (c (make-symbol "c"))
620 (data (make-symbol "data")))
621 `(let ((,tag-value ,tag))
622 (declare (lexical ,tag-value))
623 (condition-case ,c
624 (let ((%catch t))
625 ,@body)
626 (throw
627 (let ((,data (cdr ,c)))
628 (declare (lexical ,data))
629 (if (eq (car ,data) ,tag-value)
630 (car (cdr ,data))
631 (apply #'throw ,data))))))))
632
633 (defun throw (tag value)
634 (signal (if %catch 'throw 'no-catch) (list tag value)))
635
636 ;;; I/O
637
638 (defun princ (object)
639 (funcall (@ (guile) display) object))
640
641 (defun print (object)
642 (funcall (@ (guile) write) object))
643
644 (defun prin1 (object)
645 (funcall (@ (guile) write) object))
646
647 (defun terpri ()
648 (funcall (@ (guile) newline)))
649
650 (defun format* (stream string &rest args)
651 (apply (@ (guile) format) stream string args))
652
653 (defun send-string-to-terminal (string)
654 (princ string))
655
656 (defun read-from-minibuffer (prompt &rest ignore)
657 (princ prompt)
658 (let ((value (funcall (@ (ice-9 rdelim) read-line))))
659 (if (funcall (@ (guile) eof-object?) value)
660 ""
661 value)))
662
663 (defun prin1-to-string (object)
664 (format* nil "~S" object))
665
666 ;; Random number generation
667
668 (defvar %random-state (funcall (@ (guile) copy-random-state)
669 (@ (guile) *random-state*)))
670
671 (defun random (&optional limit)
672 (if (eq limit t)
673 (setq %random-state
674 (funcall (@ (guile) random-state-from-platform))))
675 (funcall (@ (guile) random)
676 (if (wholenump limit)
677 limit
678 (@ (guile) most-positive-fixnum))
679 %random-state))
680
681 (defmacro save-excursion (&rest body)
682 `(call-with-save-excursion #'(lambda () ,@body)))
683
684 (defmacro save-current-buffer (&rest body)
685 `(call-with-save-current-buffer #'(lambda () ,@body)))
686
687 (defmacro save-restriction (&rest body)
688 `(call-with-save-restriction #'(lambda () ,@body)))
689
690 (defmacro track-mouse (&rest body)
691 `(call-with-track-mouse #'(lambda () ,@body)))
692
693 (defmacro setq-default (var value &rest args)
694 `(progn (set-default ',var ,value)
695 ,(if (null args)
696 var
697 `(setq-default ,@args))))
698
699 (defmacro catch (tag &rest body)
700 `(call-with-catch ,tag #'(lambda () ,@body)))
701
702 (defmacro condition-case (var bodyform &rest args)
703 (if (consp args)
704 (let* ((handler (car args))
705 (handlers (cdr args))
706 (handler-conditions (car handler))
707 (handler-body (cdr handler)))
708 `(call-with-handler ',var
709 ',handler-conditions
710 #'(lambda () ,@handler-body)
711 #'(lambda ()
712 (condition-case ,var
713 ,bodyform
714 ,@handlers))))
715 bodyform))
716
717 (defun backtrace-frame (nframes)
718 (let* ((stack (funcall (@ (guile) make-stack) t))
719 (frame (stack-ref stack nframes))
720 (proc (funcall (@ (guile) frame-procedure) frame))
721 (pname (or (and (%functionp proc)
722 (funcall (@ (guile) procedure-name) proc))
723 proc))
724 (args (funcall (@ (guile) frame-arguments) frame)))
725 (cons t (cons pname args))))
726
727 (defun backtrace ()
728 (interactive)
729 (let* ((stack (funcall (@ (guile) make-stack) t))
730 (frame (funcall (@ (guile) stack-ref) stack 1))
731 (space (funcall (@ (guile) integer->char) 32)))
732 (while frame
733 (princ (string 32 32))
734 (let ((proc (funcall (@ (guile) frame-procedure) frame)))
735 (prin1 (or (and (%functionp proc)
736 (funcall (@ (guile) procedure-name) proc))
737 proc)))
738 (prin1 (funcall (@ (guile) frame-arguments) frame))
739 (terpri)
740 (setq frame (funcall (@ (guile) frame-previous) frame)))
741 nil))
742
743 (defun %set-eager-macroexpansion-mode (ignore)
744 nil)