1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-29 00:10:21 +02:00

Implemented unless, when and dotimes using built-in macros.

* module/language/elisp/README: Document that.
* module/language/elisp/runtime.scm: Defined built-in-macro macro.
* module/language/elisp/runtime/macro-slot.scm: Implement unless, when, dotimes.
* test-suite/tests/elisp-compiler.test: Test for those constructs.
This commit is contained in:
Daniel Kraft 2009-07-18 18:38:42 +02:00
parent 570c12aca7
commit 7d1a978289
4 changed files with 92 additions and 20 deletions

View file

@ -6,10 +6,10 @@ as status information.
Already implemented:
* progn
* if, cond
* and, or
* if, cond, when, unless
* not, and, or
* referencing and setting (setq) variables
* while
* while, dotimes
* let, let*
* lambda expressions, function calls using list notation
* some built-ins (mainly numbers/arithmetic)
@ -19,8 +19,7 @@ Already implemented:
Especially still missing:
* other progX forms, will be done in macros
* where, unless, will be done in macros
* dolist, dotimes using macros
* dolist using macros
* catch/throw, unwind-protect
* real elisp reader instead of Scheme's
* set, makunbound, boundp functions

View file

@ -20,8 +20,8 @@
;;; Code:
(define-module (language elisp runtime)
#:export (void nil-value t-value elisp-bool)
#:export-syntax (built-in-func))
#:export (void nil-value t-value elisp-bool macro-error)
#:export-syntax (built-in-func built-in-macro))
; This module provides runtime support for the Elisp front-end.
@ -38,6 +38,13 @@
(define t-value #t)
; Report an error during macro compilation, that means some special compilation
; (syntax) error.
(define (macro-error msg . args)
(apply error msg args))
; Convert a scheme boolean to Elisp.
(define (elisp-bool b)
@ -46,9 +53,17 @@
nil-value))
; Define a predefined function; convenient macro for this task.
; Define a predefined function or predefined macro for use in the function-slot
; and macro-slot modules, respectively.
(define-macro (built-in-func name value)
`(begin
(define-public ,name (make-fluid))
(fluid-set! ,name ,value)))
(define-syntax built-in-func
(syntax-rules ()
((_ name value)
(begin
(define-public name (make-fluid))
(fluid-set! name value)))))
(define-syntax built-in-macro
(syntax-rules ()
((_ name value)
(define-public name value))))

View file

@ -19,9 +19,46 @@
;;; Code:
(define-module (language elisp runtime macro-slot))
(define-module (language elisp runtime macro-slot)
#:use-module (language elisp runtime))
; This module contains the macro definitions of elisp symbols. In contrast to
; the other runtime modules, those are used directly during compilation, of
; course, so not really in runtime. But I think it fits well to the others
; here.
; Define the conditionals when and unless as macros.
(built-in-macro when
(lambda (condition . thens)
`(if ,condition (progn ,@thens) nil)))
(built-in-macro unless
(lambda (condition . elses)
`(if ,condition nil (progn ,@elses))))
; Define the dotimes and dolist iteration macros.
; As the variable has to be bound locally for elisp, this needs to go through
; the dynamic scoping fluid system. So we can't speed these forms up by
; implementing them directly in the compiler with just a lexical variable
; anyways.
(built-in-macro dotimes
(lambda (args . body)
(if (or (not (list? args))
(< (length args) 2)
(> (length args) 3))
(macro-error "invalid dotimes arguments" args)
(let ((var (car args))
(count (cadr args)))
(if (not (symbol? var))
(macro-error "expected symbol as dotimes variable"))
`(let ((,var 0))
(while (< ,var ,count)
,@body
(setq ,var (1+ ,var)))
,@(if (= (length args) 3)
(list (caddr args))
'()))))))

View file

@ -56,12 +56,24 @@
(pass-if-equal "succeeding if" 1
(if t 1 2))
(pass-if-equal "failing if" 3
(if nil
1
(setq a 2)
(setq a (1+ a))
a))
(pass-if "failing if"
(and (= (if nil
1
(setq a 2) (setq a (1+ a)) a)
3)
(equal (if nil 1) nil)))
(pass-if-equal "failing when" nil-value
(when nil 1 2 3))
(pass-if-equal "succeeding when" 42
(progn (setq a 0)
(when t (setq a 42) a)))
(pass-if-equal "failing unless" nil-value
(unless t 1 2 3))
(pass-if-equal "succeeding unless" 42
(progn (setq a 0)
(unless nil (setq a 42) a)))
(pass-if-equal "empty cond" nil-value
(cond))
@ -101,7 +113,16 @@
(while (<= i 5)
(setq prod (* i prod))
(setq i (1+ i)))
prod)))
prod))
(pass-if "dotimes"
(progn (setq a 0)
(setq count 100)
(setq b (dotimes (i count)
(setq j (1+ i))
(setq a (+ a j))))
(setq c (dotimes (i 10 42) nil))
(and (= a 5050) (equal b nil) (= c 42)))))
; Test handling of variables.