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:
parent
570c12aca7
commit
7d1a978289
4 changed files with 92 additions and 20 deletions
|
@ -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
|
||||
|
|
|
@ -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))))
|
||||
|
|
|
@ -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))
|
||||
'()))))))
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue