~ubuntu-branches/ubuntu/trusty/librep/trusty

« back to all changes in this revision

Viewing changes to lisp/rep/lang/define.jl

  • Committer: Bazaar Package Importer
  • Author(s): Christian Marillat
  • Date: 2001-11-13 15:06:22 UTC
  • Revision ID: james.westby@ubuntu.com-20011113150622-vgmgmk6srj3kldr3
Tags: upstream-0.15.2
ImportĀ upstreamĀ versionĀ 0.15.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
;; define.jl -- Scheme define syntax
 
2
;; Copyright (C) 2000 John Harper <john@dcs.warwick.ac.uk>
 
3
 
 
4
;; $Id: define.jl,v 1.32 2001/08/08 06:00:20 jsh Exp $
 
5
 
 
6
;; This file is part of librep.
 
7
 
 
8
;; librep is free software; you can redistribute it and/or modify it
 
9
;; under the terms of the GNU General Public License as published by
 
10
;; the Free Software Foundation; either version 2, or (at your option)
 
11
;; any later version.
 
12
 
 
13
;; librep is distributed in the hope that it will be useful, but
 
14
;; WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
;; GNU General Public License for more details.
 
17
 
 
18
;; You should have received a copy of the GNU General Public License
 
19
;; along with librep; see the file COPYING.  If not, write to
 
20
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
21
 
 
22
(declare (unsafe-for-call/cc))
 
23
 
 
24
(declare (in-module rep.lang.interpreter))
 
25
 
 
26
(open-structures '(rep.lang.backquote))
 
27
 
 
28
;; Commentary:
 
29
 
 
30
;; This attempts to implement Scheme's elegant block-structured
 
31
;; function definitions. It will scan leading `define' forms from all
 
32
;; `define', `let', `let*', and `lambda' special forms (and from any
 
33
;; macros in terms of these special forms)
 
34
 
 
35
;; Note that the rep interpreter and compiler support scheme-like
 
36
;; lambda lists natively, so things like (define (foo . bar) ..) will
 
37
;; work correctly
 
38
 
 
39
;; Note^2 that this doesn't work quite like Scheme define, in that the
 
40
;; outermost define always affects the global environment (unless
 
41
;; within a with-internal-definitions block) [the reason for this
 
42
;; ugliness is to avoid redefining lambda]
 
43
 
 
44
;; List of currently bound variables. Used to avoid expanding macros
 
45
;; that have been rebound locally
 
46
(%define define-bound-vars (make-fluid '()))
 
47
 
 
48
;; returns (SYM DEF [DOC])
 
49
(defun define-parse (args)
 
50
  (if (consp (car args))
 
51
      (define-parse `(,(caar args) (lambda ,(cdar args) ,@(cdr args))))
 
52
    (list* (car args) (define-scan-form (cadr args))
 
53
           (and (stringp (caddr args)) (list (caddr args))))))
 
54
 
 
55
(defun define-scan-internals (body)
 
56
  (let
 
57
      (defs)
 
58
    (while (eq (caar body) 'define)
 
59
      (setq defs (cons (define-parse (cdar body)) defs))
 
60
      (setq body (cdr body)))
 
61
    (if defs
 
62
        (list* 'letrec
 
63
               (mapcar (lambda (def)
 
64
                         (list (car def) (cadr def))) (nreverse defs))
 
65
               (define-scan-body body))
 
66
      (let ((new-body (define-scan-body body)))
 
67
        (if (null (cdr new-body))
 
68
            (car new-body)
 
69
          (cons 'progn new-body))))))
 
70
 
 
71
(defun define-scan-body (body)
 
72
  (let ((new (mapcar define-scan-form body)))
 
73
    (if (equal new body) body new)))
 
74
 
 
75
(defun define-macroexpand-1 (form)
 
76
  (if (memq (car form) (fluid define-bound-vars))
 
77
      form
 
78
    (macroexpand-1 form macro-environment)))
 
79
 
 
80
;; This needs to handle all special forms. It also needs to handle any
 
81
;; macros that the compiler wants to see without being expanded..
 
82
(defun define-scan-form (form)
 
83
  (if (atom form)
 
84
      form
 
85
    (case (if (memq (car form) (fluid define-bound-vars)) '() (car form))
 
86
      ((let)
 
87
       (if (and (eq (car form) 'let) (cadr form) (symbolp (cadr form)))
 
88
           ;; named let, expand
 
89
           (define-scan-form (define-macroexpand-1 form))
 
90
         (let loop ((rest (cadr form))
 
91
                    (vars '())
 
92
                    (clauses '()))
 
93
           (cond ((null rest)
 
94
                  (list 'let (nreverse clauses)
 
95
                        (let-fluids ((define-bound-vars
 
96
                                      (nconc vars (fluid define-bound-vars))))
 
97
                          (define-scan-internals (cddr form)))))
 
98
                 ((consp (car rest))
 
99
                  (loop (cdr rest)
 
100
                        (cons (caar rest) vars)
 
101
                        (cons (cons (caar rest)
 
102
                                    (define-scan-body (cdar rest))) clauses)))
 
103
                 (t (loop (cdr rest)
 
104
                          (cons (car rest) vars)
 
105
                          (cons (car rest) clauses)))))))
 
106
 
 
107
      ((let*)
 
108
       (let-fluids ((define-bound-vars (fluid define-bound-vars)))
 
109
         (let loop ((rest (cadr form))
 
110
                    (clauses '()))
 
111
           (cond ((null rest)
 
112
                  (list 'let* (nreverse clauses)
 
113
                        (define-scan-internals (cddr form))))
 
114
                 ((consp (car rest))
 
115
                  (fluid-set define-bound-vars
 
116
                             (cons (caar rest) (fluid define-bound-vars)))
 
117
                  (loop (cdr rest)
 
118
                        (cons (cons (caar rest)
 
119
                                    (define-scan-body (cdar rest))) clauses)))
 
120
                 (t
 
121
                  (fluid-set define-bound-vars
 
122
                             (cons (car rest) (fluid define-bound-vars)))
 
123
                  (loop (cdr rest)
 
124
                        (cons (car rest) clauses)))))))
 
125
 
 
126
      ((letrec)
 
127
       (let-fluids ((define-bound-vars
 
128
                     (nconc (mapcar (lambda (x) (or (car x) x)) (cadr form))
 
129
                            (fluid define-bound-vars))))
 
130
         (list 'letrec
 
131
               (mapcar (lambda (x)
 
132
                         (if (consp x)
 
133
                             (cons (car x) (define-scan-body (cdr x)))
 
134
                           x)) (cadr form))
 
135
               (define-scan-internals (cddr form)))))
 
136
 
 
137
      ((let-fluids)
 
138
       (list 'let-fluids
 
139
             (mapcar (lambda (x)
 
140
                       (if (consp x)
 
141
                           (cons (car x) (define-scan-body (cdr x)))
 
142
                         x)) (cadr form))
 
143
             (define-scan-internals (cddr form))))
 
144
 
 
145
      ((setq)
 
146
       (let loop ((rest (cdr form))
 
147
                  (out nil))
 
148
         (if rest
 
149
             (loop (cddr rest)
 
150
                   (cons (list (car rest)
 
151
                               (define-scan-form (cadr rest))) out))
 
152
           (cons (car form) (apply nconc (nreverse out))))))
 
153
 
 
154
      ((cond)
 
155
       (cons 'cond (mapcar (lambda (clause)
 
156
                             (define-scan-body clause)) (cdr form))))
 
157
 
 
158
      ((case)
 
159
       (list* 'case
 
160
              (define-scan-form (nth 1 form))
 
161
              (mapcar (lambda (clause)
 
162
                        (cons (car clause) (define-scan-body (cdr clause))))
 
163
                      (nthcdr 2 form))))
 
164
 
 
165
      ((condition-case)
 
166
       (let ((var (if (eq (cadr form) 'nil) nil (cadr form))))
 
167
         (let-fluids ((define-bound-vars (cons var (fluid define-bound-vars))))
 
168
           (list* 'condition-case (cadr form)
 
169
                  (define-scan-body (cddr form))))))
 
170
 
 
171
      ((catch unwind-protect progn)
 
172
       (cons (car form) (define-scan-body (cdr form))))
 
173
 
 
174
      ((quote structure-ref) form)
 
175
 
 
176
      ((lambda)
 
177
       (let ((vars (let loop ((rest (cadr form))
 
178
                              (vars '()))
 
179
                     (cond ((null rest) vars)
 
180
                           ((memq (or (caar rest) (car rest))
 
181
                                  '(#!optional #!key #!rest &optional &rest))
 
182
                            (loop (cdr rest) vars))
 
183
                           (t (loop (cdr rest) (cons (or (caar rest)
 
184
                                                         (car rest)) vars))))))
 
185
             (body (nthcdr 2 form))
 
186
             (header nil))
 
187
         ;; skip doc strings and interactive decls..
 
188
         (while (or (stringp (car body)) (eq (caar body) 'interactive))
 
189
           (setq header (cons (car body) header))
 
190
           (setq body (cdr body)))
 
191
         `(lambda ,(cadr form)
 
192
            ,@(nreverse header)
 
193
            ,(let-fluids ((define-bound-vars
 
194
                           (nconc vars (fluid define-bound-vars))))
 
195
               (define-scan-internals body)))))
 
196
 
 
197
      ((defvar)
 
198
       (list* 'defvar (nth 1 form) (define-scan-form (nth 2 form))
 
199
              (nthcdr 3 form)))
 
200
 
 
201
      ((structure define-structure declare) form)
 
202
 
 
203
      (t (let ((expansion (define-macroexpand-1 form)))
 
204
           (if (eq expansion form)
 
205
               (define-scan-body form)
 
206
             (define-scan-form expansion)))))))
 
207
 
 
208
;;;###autoload
 
209
(defmacro define (#!rest args)
 
210
  (let ((def (define-parse args)))
 
211
    (let ((var (car def))
 
212
          (value (cadr def))
 
213
          (doc (caddr def)))
 
214
      (if (eq (car value) 'lambda)
 
215
          `(defun ,var ,(cadr value)
 
216
             ,@(and doc (list doc))
 
217
             ,@(let ((body (cddr value)))
 
218
                 (if (and (eq (car body) 'progn) (null (cdr body)))
 
219
                     (cdar body)
 
220
                   body)))
 
221
        (cons '%define def)))))
 
222
 
 
223
;;;###autoload
 
224
(defmacro define-macro (#!rest args)
 
225
  (let ((def (define-parse args)))
 
226
    (let ((var (car def))
 
227
          (value (cadr def))
 
228
          (doc (caddr def)))
 
229
      (if (eq (car value) 'lambda)
 
230
          `(defmacro ,var ,(cadr value)
 
231
             ,@(and doc (list doc))
 
232
             ,@(let ((body (cddr value)))
 
233
                 (if (and (eq (car body) 'progn) (null (cdr body)))
 
234
                     (cdar body)
 
235
                   body)))
 
236
        ;; can only expand to defmacro forms (for the compiler's sake)
 
237
        (error "Macros must be constant lambdas: %s" (car def))))))
 
238
 
 
239
;;;###autoload
 
240
(defmacro with-internal-definitions (#!rest body)
 
241
  (define-scan-internals body))