From e7602cd02d46a7da01815d1cdc7461ce2000593f Mon Sep 17 00:00:00 2001 From: "Taylor R. Campbell" Date: Fri, 9 Dec 2005 20:25:59 +0000 Subject: [PATCH] Implement SRFI 2: AND-LET* --- v7/doc/ref-manual/scheme.texinfo | 5 ++- v7/doc/ref-manual/special-forms.texi | 59 ++++++++++++++++++++++++++-- v7/src/edwin/schmod.scm | 3 +- v7/src/runtime/mit-syntax.scm | 49 ++++++++++++++++++++++- 4 files changed, 108 insertions(+), 8 deletions(-) diff --git a/v7/doc/ref-manual/scheme.texinfo b/v7/doc/ref-manual/scheme.texinfo index 86b4aa884..673dcade8 100644 --- a/v7/doc/ref-manual/scheme.texinfo +++ b/v7/doc/ref-manual/scheme.texinfo @@ -1,10 +1,10 @@ \input texinfo @c -*-texinfo-*- -@comment $Id: scheme.texinfo,v 1.134 2005/05/20 02:15:49 cph Exp $ +@comment $Id: scheme.texinfo,v 1.135 2005/12/09 20:25:58 riastradh Exp $ @comment %**start of header @setfilename mit-scheme-ref @set EDITION 1.103 @set VERSION 7.7.90+ -@set UPDATED 2005-05-19 +@set UPDATED 2005-12-09 @settitle MIT/GNU Scheme @value{VERSION} @comment %**end of header @setchapternewpage odd @@ -179,6 +179,7 @@ SRFI syntax * cond-expand (SRFI 0):: * receive (SRFI 8):: +* and-let* (SRFI 2):: * define-record-type (SRFI 9):: Numbers diff --git a/v7/doc/ref-manual/special-forms.texi b/v7/doc/ref-manual/special-forms.texi index 15f0b393b..958690a25 100644 --- a/v7/doc/ref-manual/special-forms.texi +++ b/v7/doc/ref-manual/special-forms.texi @@ -1,9 +1,9 @@ @c This file is part of the MIT/GNU Scheme Reference Manual. -@c $Id: special-forms.texi,v 1.2 2003/04/25 20:40:22 cph Exp $ +@c $Id: special-forms.texi,v 1.3 2005/12/09 20:25:59 riastradh Exp $ @c Copyright 1991,1992,1993,1994,1995 Massachusetts Institute of Technology @c Copyright 1996,1997,1999,2000,2001 Massachusetts Institute of Technology -@c Copyright 2002,2003 Massachusetts Institute of Technology +@c Copyright 2002,2003,2005 Massachusetts Institute of Technology @c See file scheme.texinfo for copying conditions. @node Special Forms, Equivalence Predicates, Overview, Top @@ -2771,6 +2771,7 @@ existing practice rather than introducing new functionality. @menu * cond-expand (SRFI 0):: * receive (SRFI 8):: +* and-let* (SRFI 2):: * define-record-type (SRFI 9):: @end menu @@ -2847,7 +2848,7 @@ special form is allowed. This is an extension of the semantics defined by @acronym{SRFI 0}, which only allows @code{cond-expand} at top level. @end deffn -@node receive (SRFI 8), define-record-type (SRFI 9), cond-expand (SRFI 0), SRFI syntax +@node receive (SRFI 8), and-let* (SRFI 2), cond-expand (SRFI 0), SRFI syntax @subsection receive (SRFI 8) @cindex SRFI 8 @@ -2939,7 +2940,57 @@ the extended environment. The results of the last expression in the body are the values of the @samp{receive} expression. @end deffn -@node define-record-type (SRFI 9), , receive (SRFI 8), SRFI syntax +@node and-let* (SRFI 2), define-record-type (SRFI 9), receive (SRFI 8), SRFI syntax +@subsection and-let* (SRFI 2) + +@cindex SRFI 2 +@uref{http://srfi.schemers.org/srfi-2/srfi-2.html,@acronym{SRFI} 2} +provides a form that combines @samp{and} and @samp{let*} for a +logically short-circuiting sequential binding operator. + +@deffn {special form} and-let* (clause @dots{}) body +Runs through each of the clauses left-to-right, short-circuiting like +@samp{and} in that the first false clause will result in the whole +@samp{and-let*} form returning false. If a body is supplied, and all +of the clauses evaluate true, then the body is evaluated sequentially +as if in a @samp{begin} form, and the value of the @samp{and-let*} +expression is the value of the last body form, evaluated in a tail +position with respect to the @samp{and-let*} expression. If no body +is supplied, the value of the last clause, also evaluated in a tail +position with respect to the @samp{and-let*} expression, is used +instead. + +Each @var{clause} should have one of the following forms: + +@table @samp +@item @var{identifier} +in which case @var{identifier}'s value is tested. + +@item (@var{expression}) +in which case the value of @var{expression} is tested. + +@item (@var{identifier} @var{expression}) +in which case @var{expression} is evaluated, and, if its value is not +false, @var{identifier} is bound to that value for the remainder of +the clauses and the optional body. +@end table +@end deffn + +@comment More examples, please! + +Example: + +@example +@group +(and-let* ((list (compute-list)) + ((pair? list)) + (item (car list)) + ((integer? item))) + (sqrt item)) +@end group +@end example + +@node define-record-type (SRFI 9), , and-let* (SRFI 2), SRFI syntax @subsection define-record-type (SRFI 9) @cindex SRFI 9 diff --git a/v7/src/edwin/schmod.scm b/v7/src/edwin/schmod.scm index 8b2b88999..333c921ae 100644 --- a/v7/src/edwin/schmod.scm +++ b/v7/src/edwin/schmod.scm @@ -1,6 +1,6 @@ #| -*-Scheme-*- -$Id: schmod.scm,v 1.72 2005/06/10 01:50:46 cph Exp $ +$Id: schmod.scm,v 1.73 2005/12/09 20:25:59 riastradh Exp $ Copyright 1986,1989,1990,1991,1992,1998 Massachusetts Institute of Technology Copyright 2000,2001,2002,2003,2004,2005 Massachusetts Institute of Technology @@ -179,6 +179,7 @@ The following commands evaluate Scheme expressions: CALL-WITH-OUTPUT-FILE WITH-OUTPUT-TO-FILE) ;; SRFI keywords: + (1 AND-LET*) (2 RECEIVE) (3 DEFINE-RECORD-TYPE) diff --git a/v7/src/runtime/mit-syntax.scm b/v7/src/runtime/mit-syntax.scm index 44a24f857..9d7306200 100644 --- a/v7/src/runtime/mit-syntax.scm +++ b/v7/src/runtime/mit-syntax.scm @@ -1,6 +1,6 @@ #| -*-Scheme-*- -$Id: mit-syntax.scm,v 14.23 2005/11/20 04:12:59 riastradh Exp $ +$Id: mit-syntax.scm,v 14.24 2005/12/09 20:25:59 riastradh Exp $ Copyright 1989,1990,1991,2001,2002,2003 Massachusetts Institute of Technology Copyright 2004 Massachusetts Institute of Technology @@ -335,6 +335,7 @@ USA. (define supported-srfi-features '(SRFI-0 + SRFI-2 SRFI-6 SRFI-8 SRFI-9 @@ -810,6 +811,52 @@ USA. (syntax-check '(KEYWORD EXPRESSION) form history) (descend-quasiquote (cadr form) 0 finalize-quasiquote))))))) +;;;; SRFI 2: AND-LET* + +;;; The SRFI document is a little unclear about the semantics, imposes +;;; the weird restriction that variables may be duplicated (citing +;;; LET*'s similar restriction, which doesn't actually exist), and the +;;; reference implementation is highly non-standard and hard to +;;; follow. This passes all of the tests except for the one that +;;; detects duplicate bound variables, though. + +(define-er-macro-transformer 'AND-LET* system-global-environment + (lambda (form rename compare) + compare + (let ((%and (rename 'AND)) + (%let (rename 'LET)) + (%begin (rename 'BEGIN))) + (cond ((syntax-match? '(() * FORM) (cdr form)) + `(,%begin #T ,@(cddr form))) + ((syntax-match? '((* DATUM) * FORM) (cdr form)) + (let ((clauses (cadr form)) + (body (cddr form))) + (define (expand clause recur) + (cond ((syntax-match? 'IDENTIFIER clause) + (recur clause)) + ((syntax-match? '(EXPRESSION) clause) + (recur (car clause))) + ((syntax-match? '(IDENTIFIER EXPRESSION) clause) + (let ((tail (recur (car clause)))) + (and tail `(,%let (,clause) ,tail)))) + (else #f))) + (define (recur clauses make-body) + (expand (car clauses) + (let ((clauses (cdr clauses))) + (if (null? clauses) + make-body + (lambda (conjunct) + `(,%and ,conjunct + ,(recur clauses make-body))))))) + (or (recur clauses + (if (null? body) + (lambda (conjunct) conjunct) + (lambda (conjunct) + `(,%and ,conjunct (,%begin ,@body))))) + (ill-formed-syntax form)))) + (else + (ill-formed-syntax form)))))) + ;;;; MIT-specific syntax (define-er-macro-transformer 'ACCESS system-global-environment -- 2.25.1