~peter-pearse/ubuntu/natty/guile-1.8/prop001

« back to all changes in this revision

Viewing changes to srfi/srfi-16.scm

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Schepler
  • Date: 2006-11-09 03:11:16 UTC
  • Revision ID: james.westby@ubuntu.com-20061109031116-hu0q1jxqg12y6yeg
Tags: upstream-1.8.1+1
ImportĀ upstreamĀ versionĀ 1.8.1+1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;;; srfi-16.scm --- case-lambda
 
2
 
 
3
;; Copyright (C) 2001, 2002, 2006 Free Software Foundation, Inc.
 
4
;;
 
5
;; This library is free software; you can redistribute it and/or
 
6
;; modify it under the terms of the GNU Lesser General Public
 
7
;; License as published by the Free Software Foundation; either
 
8
;; version 2.1 of the License, or (at your option) any later version.
 
9
;; 
 
10
;; This library is distributed in the hope that it will be useful,
 
11
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
;; Lesser General Public License for more details.
 
14
;; 
 
15
;; You should have received a copy of the GNU Lesser General Public
 
16
;; License along with this library; if not, write to the Free Software
 
17
;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 
 
19
;;; Author: Martin Grabmueller
 
20
 
 
21
;;; Commentary:
 
22
 
 
23
;; Implementation of SRFI-16.  `case-lambda' is a syntactic form
 
24
;; which permits writing functions acting different according to the
 
25
;; number of arguments passed.
 
26
;;
 
27
;; The syntax of the `case-lambda' form is defined in the following
 
28
;; EBNF grammar.
 
29
;;
 
30
;; <case-lambda>
 
31
;;    --> (case-lambda <case-lambda-clause>)
 
32
;; <case-lambda-clause>
 
33
;;    --> (<signature> <definition-or-command>*)
 
34
;; <signature>
 
35
;;    --> (<identifier>*)
 
36
;;      | (<identifier>* . <identifier>)
 
37
;;      | <identifier>
 
38
;;
 
39
;; The value returned by a `case-lambda' form is a procedure which
 
40
;; matches the number of actual arguments against the signatures in
 
41
;; the various clauses, in order.  The first matching clause is
 
42
;; selected, the corresponding values from the actual parameter list
 
43
;; are bound to the variable names in the clauses and the body of the
 
44
;; clause is evaluated.
 
45
 
 
46
;;; Code:
 
47
 
 
48
(define-module (srfi srfi-16)
 
49
  :export-syntax (case-lambda))
 
50
 
 
51
(cond-expand-provide (current-module) '(srfi-16))
 
52
 
 
53
(define-macro (case-lambda . clauses)
 
54
 
 
55
  ;; Return the length of the list @var{l}, but allow dotted list.
 
56
  ;;
 
57
  (define (alength l)
 
58
    (cond ((null? l) 0)
 
59
          ((pair? l) (+ 1 (alength (cdr l))))
 
60
          (else 0)))
 
61
 
 
62
  ;; Return @code{#t} if @var{l} is a dotted list, @code{#f} if it is
 
63
  ;; a normal list.
 
64
  ;;
 
65
  (define (dotted? l)
 
66
    (cond ((null? l) #f)
 
67
          ((pair? l) (dotted? (cdr l)))
 
68
          (else #t)))
 
69
 
 
70
  ;; Return the expression for accessing the @var{index}th element of
 
71
  ;; the list called @var{args-name}.  If @var{tail?} is true, code
 
72
  ;; for accessing the list-tail is generated, otherwise for accessing
 
73
  ;; the list element itself.
 
74
  ;;
 
75
  (define (accessor args-name index tail?)
 
76
    (if tail?
 
77
        (case index
 
78
          ((0) `,args-name)
 
79
          ((1) `(cdr ,args-name))
 
80
          ((2) `(cddr ,args-name))
 
81
          ((3) `(cdddr ,args-name))
 
82
          ((4) `(cddddr ,args-name))
 
83
          (else `(list-tail ,args-name ,index)))
 
84
        (case index
 
85
          ((0) `(car ,args-name))
 
86
          ((1) `(cadr ,args-name))
 
87
          ((2) `(caddr ,args-name))
 
88
          ((3) `(cadddr ,args-name))
 
89
          (else `(list-ref ,args-name ,index)))))
 
90
 
 
91
  ;; Generate the binding lists of the variables of one case-lambda
 
92
  ;; clause.  @var{vars} is the (possibly dotted) list of variables
 
93
  ;; and @var{args-name} is the generated name used for the argument
 
94
  ;; list.
 
95
  ;;
 
96
  (define (gen-temps vars args-name)
 
97
    (let lp ((v vars) (i 0))
 
98
      (cond ((null? v) '())
 
99
            ((pair? v)
 
100
             (cons `(,(car v) ,(accessor args-name i #f))
 
101
                   (lp (cdr v) (+ i 1))))
 
102
            (else `((,v ,(accessor args-name i #t)))))))
 
103
 
 
104
  ;; Generate the cond clauses for each of the clauses of case-lambda,
 
105
  ;; including the parameter count check, binding of the parameters
 
106
  ;; and the code of the corresponding body.
 
107
  ;;
 
108
  (define (gen-clauses l length-name args-name)
 
109
    (cond ((null? l) (list '(else (error "too few arguments"))))
 
110
          (else
 
111
           (cons
 
112
            `((,(if (dotted? (caar l)) '>= '=)
 
113
               ,length-name ,(alength (caar l)))
 
114
              (let ,(gen-temps (caar l) args-name)
 
115
              ,@(cdar l)))
 
116
            (gen-clauses (cdr l) length-name args-name)))))
 
117
 
 
118
  (let ((args-name (gensym))
 
119
        (length-name (gensym)))
 
120
    (let ((proc
 
121
           `(lambda ,args-name
 
122
              (let ((,length-name (length ,args-name)))
 
123
                (cond ,@(gen-clauses clauses length-name args-name))))))
 
124
      proc)))
 
125
 
 
126
;;; srfi-16.scm ends here