1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-16 08:40:19 +02:00

Implemented prog1, prog2, dotimes, dolist control structures.

* module/language/elisp/README: Document it and some further ideas written down.
* module/language/elisp/compile-tree-il.scm: Implement prog1, dolist.
* module/language/elisp/runtime/macro-slot.scm: prog2 and dotimes.
* test-suite/tests/elisp-compiler.test: Test prog1, prog2, dotimes, dolist.
This commit is contained in:
Daniel Kraft 2009-07-20 20:52:00 +02:00
parent f614ca12cd
commit fb66a47a8e
4 changed files with 105 additions and 7 deletions

View file

@ -365,6 +365,47 @@
(error "non-pair expression contains unquotes" expr))
(make-const loc expr)))
; Compile a dolist construct.
; This is compiled to something along:
; (with-fluid* iter-var %nil
; (lambda ()
; (let iterate ((tail list))
; (if (null? tail)
; result
; (begin
; (fluid-set! iter-var (car tail))
; body
; (iterate (cdr tail)))))))
(define (compile-dolist loc var iter-list result body)
(let* ((tailvar (gensym))
(iterate (gensym))
(tailref (make-lexical-ref loc tailvar tailvar))
(iterate-func (make-lambda loc `(,tailvar) `(,tailvar) '()
(make-conditional loc
(call-primitive loc 'null? tailref)
(compile-expr result)
(make-sequence loc
`(,(set-variable! loc var value-slot
(call-primitive loc 'car tailref))
,@(map compile-expr body)
,(make-application loc
(make-lexical-ref loc iterate iterate)
(list (call-primitive loc 'cdr
tailref)))))))))
(make-sequence loc
(list (ensure-fluid! loc var value-slot)
(call-primitive loc 'with-fluid*
(make-module-ref loc value-slot var #t)
(nil-value loc)
(make-lambda loc '() '() '()
(make-letrec loc `(,iterate) `(,iterate) `(,iterate-func)
(make-application loc
(make-lexical-ref loc iterate iterate)
(list (compile-expr iter-list))))))))))
; Compile a symbol expression. This is a variable reference or maybe some
; special value like nil.
@ -384,6 +425,16 @@
((progn . ,forms)
(make-sequence loc (map compile-expr forms)))
; I chose to implement prog1 directly (not with macros) so that the
; temporary variable used can be a lexical one that is not backed by a fluid
; for better performance.
((prog1 ,form1 . ,forms)
(let ((temp (gensym)))
(make-let loc `(,temp) `(,temp) `(,(compile-expr form1))
(make-sequence loc
(append (map compile-expr forms)
(list (make-lexical-ref loc temp temp)))))))
((if ,condition ,ifclause)
(make-conditional loc (compile-expr condition)
(compile-expr ifclause)
@ -544,6 +595,13 @@
(make-letrec loc '(iterate) (list itersym) (list iter-thunk)
iter-call)))
; dolist is treated here rather than as macro because it can take advantage
; of a non-fluid-based variable.
((dolist (,var ,iter-list) . ,body) (guard (symbol? var))
(compile-dolist loc var iter-list 'nil body))
((dolist (,var ,iter-list ,result) . ,body) (guard (symbol? var))
(compile-dolist loc var iter-list result body))
; Either (lambda ...) or (function (lambda ...)) denotes a lambda-expression
; that should be compiled.
((lambda ,args . ,body)