mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-03 13:20:26 +02:00
while in terms of syntax-case
* module/ice-9/boot-9.scm (while): Reimplement in terms of syntax-case. Prompt inlining is coming later. * test-suite/tests/syntax.test ("while"): Update the expected syntax errors.
This commit is contained in:
parent
322a36ce9f
commit
10e69149f6
2 changed files with 46 additions and 25 deletions
|
@ -2842,28 +2842,46 @@ module '(ice-9 q) '(make-q q-length))}."
|
||||||
;;; with `continue' and `break'.
|
;;; with `continue' and `break'.
|
||||||
;;;
|
;;;
|
||||||
|
|
||||||
;; The inner `do' loop avoids re-establishing a catch every iteration,
|
;; The inliner will remove the prompts at compile-time if it finds that
|
||||||
;; that's only necessary if continue is actually used. A new key is
|
;; `continue' or `break' are not used.
|
||||||
;; generated every time, so break and continue apply to their originating
|
|
||||||
;; `while' even when recursing.
|
|
||||||
;;
|
;;
|
||||||
;; FIXME: This macro is unintentionally unhygienic with respect to let,
|
(define-syntax while
|
||||||
;; make-symbol, do, throw, catch, lambda, and not.
|
(lambda (x)
|
||||||
;;
|
(syntax-case x ()
|
||||||
(define-macro (while cond . body)
|
((while cond body ...)
|
||||||
(let ((keyvar (make-symbol "while-keyvar")))
|
#`(let ((break-tag (make-prompt-tag "break"))
|
||||||
`(let ((,keyvar (make-symbol "while-key")))
|
(continue-tag (make-prompt-tag "continue")))
|
||||||
(do ()
|
(call-with-prompt
|
||||||
((catch ,keyvar
|
break-tag
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(let ((break (lambda () (throw ,keyvar #t)))
|
(define-syntax #,(datum->syntax #'while 'break)
|
||||||
(continue (lambda () (throw ,keyvar #f))))
|
(lambda (x)
|
||||||
(do ()
|
(syntax-case x ()
|
||||||
((not ,cond))
|
((_)
|
||||||
,@body)
|
#'(abort-to-prompt break-tag))
|
||||||
#t))
|
((_ . args)
|
||||||
(lambda (key arg)
|
(syntax-violation 'break "too many arguments" x))
|
||||||
arg)))))))
|
(_
|
||||||
|
#'(lambda ()
|
||||||
|
(abort-to-prompt break-tag))))))
|
||||||
|
(let lp ()
|
||||||
|
(call-with-prompt
|
||||||
|
continue-tag
|
||||||
|
(lambda ()
|
||||||
|
(define-syntax #,(datum->syntax #'while 'continue)
|
||||||
|
(lambda (x)
|
||||||
|
(syntax-case x ()
|
||||||
|
((_)
|
||||||
|
#'(abort-to-prompt continue-tag))
|
||||||
|
((_ . args)
|
||||||
|
(syntax-violation 'continue "too many arguments" x))
|
||||||
|
(_
|
||||||
|
#'(lambda args
|
||||||
|
(apply abort-to-prompt continue-tag args))))))
|
||||||
|
(do () ((not cond)) body ...))
|
||||||
|
(lambda (k) (lp)))))
|
||||||
|
(lambda (k)
|
||||||
|
#t)))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
;;;; syntax.test --- test suite for Guile's syntactic forms -*- scheme -*-
|
;;;; syntax.test --- test suite for Guile's syntactic forms -*- scheme -*-
|
||||||
;;;;
|
;;;;
|
||||||
;;;; Copyright (C) 2001,2003,2004, 2005, 2006, 2009 Free Software Foundation, Inc.
|
;;;; Copyright (C) 2001,2003,2004, 2005, 2006, 2009, 2010 Free Software Foundation, Inc.
|
||||||
;;;;
|
;;;;
|
||||||
;;;; This library is free software; you can redistribute it and/or
|
;;;; This library is free software; you can redistribute it and/or
|
||||||
;;;; modify it under the terms of the GNU Lesser General Public
|
;;;; modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -75,6 +75,9 @@
|
||||||
(define exception:bad-cond-clause
|
(define exception:bad-cond-clause
|
||||||
(cons 'syntax-error "Bad cond clause"))
|
(cons 'syntax-error "Bad cond clause"))
|
||||||
|
|
||||||
|
(define exception:too-many-args
|
||||||
|
(cons 'syntax-error "too many arguments"))
|
||||||
|
|
||||||
|
|
||||||
(with-test-prefix "expressions"
|
(with-test-prefix "expressions"
|
||||||
|
|
||||||
|
@ -832,7 +835,7 @@
|
||||||
#t))))
|
#t))))
|
||||||
|
|
||||||
|
|
||||||
(pass-if-exception "too few args" exception:wrong-num-args
|
(pass-if-exception "too few args" exception:generic-syncase-error
|
||||||
(eval '(while) (interaction-environment)))
|
(eval '(while) (interaction-environment)))
|
||||||
|
|
||||||
(with-test-prefix "empty body"
|
(with-test-prefix "empty body"
|
||||||
|
@ -872,7 +875,7 @@
|
||||||
|
|
||||||
(with-test-prefix "break"
|
(with-test-prefix "break"
|
||||||
|
|
||||||
(pass-if-exception "too many args" exception:wrong-num-args
|
(pass-if-exception "too many args" exception:too-many-args
|
||||||
(eval '(while #t
|
(eval '(while #t
|
||||||
(break 1))
|
(break 1))
|
||||||
(interaction-environment)))
|
(interaction-environment)))
|
||||||
|
@ -945,7 +948,7 @@
|
||||||
|
|
||||||
(with-test-prefix "continue"
|
(with-test-prefix "continue"
|
||||||
|
|
||||||
(pass-if-exception "too many args" exception:wrong-num-args
|
(pass-if-exception "too many args" exception:too-many-args
|
||||||
(eval '(while #t
|
(eval '(while #t
|
||||||
(continue 1))
|
(continue 1))
|
||||||
(interaction-environment)))
|
(interaction-environment)))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue